Add existing variable to array in javascript - javascript

I've got this HTML
<div class="calListChip" id="label-bDd1aDFjNnQ2aHFxOTN2cGQyM2JhaXA2cmtAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ" title="Testkalender1">
<div class="calListChip" id="label-OWFmbmdwbWprbTRxMmFrOTNycGlicmM2bjBAZ3JvdXAuY2FsZW5kYXIuZ29vZ2xlLmNvbQ" title="Testkalender2">
and I've got this code, creating variables with the title of a html div as name and then I pass the label of the html object as parameter to the variable.
var elements = document.body.getElementsByClassName('calListChip');
var view1 = [];
//For each element found
for (var i = 0; i < elements.length; i++) {
//Variable names cant inlude spaces
var title = elements[i].title;
title = title.replace(/ +/g, "");
//create the variable
window[title] = elements[i].id;
//if 'test' exist in the title, add the variable to an array
if (elements[i].title.toLowerCase().indexOf("test") >= 0)
{
view1.push(window[title]);
}
};
But the view1 array dosent get the variable reference but instead a string with the title name, that I cant use later on.
This is the result I want
view1 : [Testkalender1, Testkalender2]
This is the result i get
view1 : ["Testkalender1", "Testkalender2"]
The problem is that i dont know how many or the title/label of the html elements so i need to dynamically create variables and then by a keyword in the title put them in the right array
Any suggestions?

It is not clear how exactly you want to generate your desired result (e.g. where the data comes from), but I can help explain what is happening with your current code. When you do this:
window[title] = elements[i].id;
You are creating a global variable of name title and assigning it the string value located in elements[i].id. So, now you have a global variable with a string in it.
When you later do this:
view1.push(window[title])
You are just pushing a copy of that string in the view1 array. That string has nothing to do with your global variable. So, view1 will end up being an array of strings.
If you want view1 to end up being an array of objects like your example here:
view1[0] = {
name: 'TestKalendrar',
items: [Testkalender1, Testkalender2]
};
Then, you have to push objects into the array, not strings.
I should add that I have no idea what your creation of global variables with this line:
window[title] = elements[i].id;
is doing to help you with your problem in any way. It should not be necessary.
I'd be happy to help you get a different result, but so far you've shown a desired array of objects, but not shown us where you get the name property from or the items property. If you can edit your question to show where those values come from, we can help with a solution to generate that.

I reworked your code a little and indeed the variables are being created see the fiddle at http://jsfiddle.net/smylydon/Q5m6Q/
var elements = document.body.getElementsByClassName('calListChip');
var view1 = [];
//For each element found
for (var i = 0, length = elements.length; i < length; i++) {
//Variable names cant inlude spaces
var title = elements[i].title;
title = title.replace(/ +/g, "");
//create the variable
window[title] = elements[i].id;
//if 'test' exist in the title, add the variable to an array
if (title.toLowerCase().indexOf("test") >= 0) {
view1.push(window[title]);
console.log('variable:', window[title]);
}
};
console.log('view1:', view1);

Related

Why does javascript reads var as a string if i add '+' to it?

I have field names in my firestore document as
videolink1-"some video link"
videolink2-"some video link"
videolink3-"some video link"
I am using a for loop to get all videolinks present in the document.
if (doc.exists) {
for (var i = 1; i == videocount; i++) { //videocount is 3
var data = doc.data();
var videolink = data.videolink+i;
//creating new paragraph
var p = '<p class ="trackvideostyle">'+"Your Video Link : "+String(videolink)+'</p>\';
document.getElementById("btn").insertAdjacentHTML('beforebegin', p);
}
But this for loop is creating var values which are being read as string and firestore is returning me NaN as I dont have these fields :
data.videolink+1
data.videolink+2 //Firestore is returning null as i dont have these document fields
data.videolink+3
How can I write for loop so that var values are created like this and firestore reads it as:
videolink1
videolink2
videolink3
I think you could try something like this,
var videolink = data[`videolink${i}`];
Refer: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
you are using "data.videolink+i" and javascript does not evaluate the value after the "." instead it is treated as the object's property. you need to use [] for evaluation. try this I hope this will work
if (doc.exists) {
for (var i = 1; i == videocount; i++) {
var data = doc.data();
var videolink = data[videolink+i];
//creating new paragraph
var p = '<p class ="trackvideostyle">'+"Your Video Link :
"+String(videolink)+'</p>\';
document.getElementById("btn").insertAdjacentHTML('beforebegin',
p);
}
Why it doesn't work
The dot operator (property accessor) has higher precendense, so it is evaluated first, so you get the value of the property and then you concatenate the value of your i variable.
What should you do
You can use another property accessor - square brackets, just like in arrays:
data['videolink']
You can build your property name inside of the square brackets:
data['videolink' + i]
or using template literals:
data[`videolink${i}`]
You can do this by using
1. template strings
..
var videolink = `${data.videolink}${i}`
..
2. concat()
..
var videolink = data.videolink.concat(i.toString());
..

How to access multi level object data with jQuery

I have this code in js, on click this happens:
var self = $(this);
self.click(function(e){
e.preventDefault();
var nid = self.parents('.innerContainer').attr('nid');
var subjectTitleNID = settings.xxxxx.yyyy["nid-" + nid]
Via HTML I can find the NID value of InnerContainer, which is the main parent.
From the console, if I run Drupal.settings.xxxx.yyyyy (where xxxx and yyyy are my destinations), I get a list of objects which are children.
["nid-463"]
["nid-465"]
["nid-466"] etc ....
nid-466 is the value assigned to VAR NID.
But what I need to find now, is:
1. How many children there are in ["nid-466"]
2. What are their values
Usually I would run a simple for loop, but I don't know how to target those values.
For example, I would do this:
for (i=0; i < dont know what to put here .length; i++) {
> Drupal.settings.xxxx.yyyy[nid-466][nid-??] // this is incorrect
}
See image for more detailed structure.
Any ideas?
Thanks
George
Use $.each loor for this:
$.each(Drupal.settings.xxxx.yyyy[nid-466], function(index, value) {
// index is a key
// value is a object
// put your code here
// console.log(value.nid);
})

access javascript array element by JSON object key

I have an array that looks like this
var Zips = [{Zip: 92880, Count:1}, {Zip:91710, Count:3}, {Zip:92672, Count:0}]
I would like to be able to access the Count property of a particular object via the Zip property so that I can increment the count when I get another zip that matches. I was hoping something like this but it's not quite right (This would be in a loop)
Zips[rows[i].Zipcode].Count
I know that's not right and am hoping that there is a solution without looping through the result set every time?
Thanks
I know that's not right and am hoping that there is a solution without
looping through the result set every time?
No, you're gonna have to loop and find the appropriate value which meets your criteria. Alternatively you could use the filter method:
var filteredZips = Zips.filter(function(element) {
return element.Zip == 92880;
});
if (filteredZips.length > 0) {
// we have found a corresponding element
var count = filteredZips[0].count;
}
If you had designed your object in a different manner:
var zips = {"92880": 1, "91710": 3, "92672": 0 };
then you could have directly accessed the Count:
var count = zips["92880"];
In the current form, you can not access an element by its ZIP-code without a loop.
You could transform your array to an object of this form:
var Zips = { 92880: 1, 91710: 3 }; // etc.
Then you can access it by
Zips[rows[i].Zipcode]
To transform from array to object you could use this
var ZipsObj = {};
for( var i=Zips.length; i--; ) {
ZipsObj[ Zips[i].Zip ] = Zips[i].Count;
}
Couple of mistakes in your code.
Your array is collection of objects
You can access objects with their property name and not property value i.e Zips[0]['Zip'] is correct, or by object notation Zips[0].Zip.
If you want to find the value you have to loop
If you want to keep the format of the array Zips and its elements
var Zips = [{Zip: 92880, Count:1}, {Zip:91710, Count:3}, {Zip:92672, Count:0}];
var MappedZips = {}; // first of all build hash by Zip
for (var i = 0; i < Zips.length; i++) {
MappedZips[Zips[i].Zip] = Zips[i];
}
MappedZips is {"92880": {Zip: 92880, Count:1}, "91710": {Zip:91710, Count:3}, "92672": {Zip:92672, Count:0}}
// then you can get Count by O(1)
alert(MappedZips[92880].Count);
// or can change data by O(1)
MappedZips[92880].Count++;
alert(MappedZips[92880].Count);
jsFiddle example
function getZip(zips, zipNumber) {
var answer = null;
zips.forEach(function(zip){
if (zip.Zip === zipNumber) answer = zip;
});
return answer;
}
This function returns the zip object with the Zip property equal to zipNumber, or null if none exists.
did you try this?
Zips[i].Zip.Count

arranging elements in to a hash array

I am trying to break a javascript object in to small array so that I can easily access the innerlevel data whenever I needed.
I have used recursive function to access all nodes inside json, using the program
http://jsfiddle.net/SvMUN/1/
What I am trying to do here is that I want to store these in to a separate array so that I cn access it like
newArray.Microsoft= MSFT, Microsoft;
newArray.Intel Corp=(INTC, Fortune 500);
newArray.Japan=Japan
newArray.Bernanke=Bernanke;
Depth of each array are different, so the ones with single level can use the same name like I ve shown in the example Bernanke. Is it possible to do it this way?
No, you reduce the Facets to a string named html - but you want an object.
function generateList(facets) {
var map = {};
(function recurse(arr) {
var join = [];
for (var i=0; i<arr.length; i++) {
var current = arr[i].term; // every object must have one!
current = current.replace(/ /g, "_");
join.push(current); // only on lowest level?
if (current in arr[i])
map[current] = recurse(arr[i][current]);
}
return join;
})(facets)
return map;
}
Demo on jsfiddle.net
To get the one-level-data, you could just add this else-statement after the if:
else
map[current] = [ current ]; // create Array manually
Altough I don't think the result (demo) makes much sense then.

Looping over array and comparing to regex

So, I'll admit to being a bit of a JS noob, but as far as I can tell, this should be working and it is not.
Background:
I have a form with 3 list boxes. The list boxes are named app1, db1, and db2. I'm using javascript to allow the user to add additional list boxes, increasing the name tag for each additional select box.
When I add additional app named boxes, the value increments properly for each additional field. If I try to add addtional db named selects, it fails to recognize the 2nd tag on the first loop through the array. This causes me to end up with 2 elements named db2. On each subsequent tag, it is recognized properly and is properly incremented.
Here is the HTML for the db1 tag:
<select name="db1">
*options*
</select>
And db2:
<select name="db2">
*options*
</select>
The tags are identical. Here is the function that I am using to figure out the next number in the sequence (note: tag is either app or db, tags is an array of all select tag names in the DOM, if I inspect tags, it gives me ['app1', 'db1', 'db2', '']):
function return_select_name(tag, tags) {
matches = new Array();
var re = new RegExp(tag + "\\d+", "g");
for (var i = 0; i < tags.length; i++) {
var found = re.exec(tags[i]);
if (found != null) {
matches.push(found[0]);
}
}
matches = matches.sort();
index = parseInt(/\d+/.exec(matches.last())) + 1;
index = tag + index;
return index;
}
If I add an app tag, it will return 'app2'. If I search for a db tag, it will return 'db2' on the first time through, db3 on the 2nd, etc, etc.
So basically, I'm sure I'm doing something wrong here.
I'd handle it by keeping a counter for db and a counter for app to use to generate the names.
var appCounter = 1;//set this manually or initialize to 0 and
var dbCounter = 2;//use your create function to add your elements on pageload
Then, when you go to create your next tag, just increment your counter and use that as the suffix for your name:
var newAppElement = document.createElement('select');
newAppElement.name = 'app' + (++appCounter);
..
// --OR for the db element--
var newDbElement = document.createElement('select');
newDbElement.name = 'db' + (++dbCounter );
..
The problem you are getting is that regex objects are stateful. You can fix your program by putting the regex creation inside the loop.
function return_select_name(tag, tags) {
matches = new Array();
// <-- regex was here
for (var i = 0; i < tags.length; i++) {
var re = new RegExp(tag + "\\d+", "g"); //<--- now is here
var found = re.exec(tags[i]);
if (found != null) {
matches.push(found[0]);
}
}
matches = matches.sort();
index = parseInt(/\d+/.exec(matches[matches.length-1])) + 1; //<--- I dont think matches.last is portable, btw
index = tag + index;
return index;
}
In any case, if I were to do this myself, I would probably prefer to avoid the cmplicated text matching and just store the next tag indices in a variable or hash map.
Another suggestion: if you put parenthesis in your regex:
// /tag(\d+)/
var re = new RegExp(tag + "(\\d+)", "g");
Then you can use found[1] to get your number directly, without the extra step afterwards.
I know this has already been answered, but I put this together as a proof of concept.
http://jsfiddle.net/zero21xxx/LzyTf/
It's an object so you could probably reuse it in different scenarios. Obviously there are ways it could be improved, but I thought it was cool so I thought I would share.
The console.debug only works in Chrome and maybe FF.

Categories

Resources