How to access multi level object data with jQuery - javascript

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);
})

Related

What am I missing in the jQuery .each() function?

I have this function that I am trying to figure out/fix and can't seem to pinpoint the issue / can't figure out a way to get it working.
Basically my CMS is spitting certain hrefs that I would like to:
Part 1) change the targeted href URL
Part 2) change the button's text
Right now I only have 2 instances of this type of button, so here's what is printing out in my console:
Part 1) for this part I get the correct urls without the characters i want to strip out.
Part 2) two instances of the button's text (See All) followed by the correct variable of btnParent for the first button and then the second button and finally one instance of "Products".
My issue is, I can't figure out how to:
Part 1) send back the stripped URL to its respective button's href as an each function.
Part 2) Have the each() function print out the new text as "See All + BLAH + Products" for each instance, and then append the new text to the respective button.
Here is the code:
function viewMoreBtn() {
var btnMain = $("li:contains('See All')");
var btnText = $("li:contains('See All')").text();
var btnParent = $("li:contains('See All')").parent('ul').prev('li').text();
// PART 1 - STRIP LINK URL OF -_-// CHARACTERS
$.each(btnMain, function(i, v) {
v = $(this).find('a').attr('href').replace('-_-//', '');
console.log(v);
});
// PART 2 - ADD LABEL TO HTML TEXT OF BTN
$.each(btnMain, function(index, value) {
value = (btnText + btnParent + 'Products');
$(btnMain).text(value);
console.log(value);
});
}
viewMoreBtn();
Thank you.
jQuery objects, as return by $(...) have a each method already on them. The element is passed as the this context. You could use that further with jQuery to act on the objects in an scoped context. Basically, you have the right code, just in the wrong scope.
Part 1
btnMain.each(function() {
var $li = $(this);
var $a = $li.find('a');
var desiredUrl = $a.attr('href').replace('-_-//', '');
$a.attr('href', desiredUrl);
});
Part 2
btnMain.each(function() {
var $li = $(this);
var btnText = $li.text();
varbtnParent = $li.parent('ul').prev('li').text();
value = (btnText + btnParent + 'Products');
console.log(value);
$li.find('a').text(value);
});
See #Zequ's answer for the iteration over the each() function in the returned btnMain.
This is how $.each( obj, function( key, value ) works: you iterate over btnMain, and for each iteration of $.each(), the function assigns the index of the iteration to i and the value of btnMain at that index to v.
$.each(btnMain, function(i, v) {
//v = $(this).find('a').attr('href').replace('-_-//', '');
console.log(i); // I am the index of $.each() iterator
console.log(v); // I am the node from the btnMain array
// I don't know if this is right without seeing your HTML, but it seems like what you want
v.find('a').attr('href').replace('-_-//', '');
});
The second $.each() follows the same pattern.
If I understood correctly, you're confusing your variables.
$.each is a function for each element of the array/object being passed. It gives you a index and the element, check the reference
In part 1, you're defining v as the string you want, you're not changing the element at all,you need something like this:
$.each(btnMain, function() {
// you're saying you got the correct URLs, so the only thing you need to do is to change the element afterwards
var element = $(this).find('a');
v = element.attr('href').replace('-_-//', '');
element.attr('href', v);
});`
Also you could use btnMain.each instead of $.each
In part 2, you are changing the value variable (it's actually the element you're iterating over), to the string you want, then you follow it by trying to change btnMain's text. This is wrong, from what I understood, btnMain is an array of two elements you can't change it's text. You should change the element's value (that you are calling value). It would be something like that
$.each(btnMain, function(index, element){
// I think this is the time you want to define the btnParent, relative to the element
var btnParent = element.parent('ul').prev('li').text();
var value = (btnText + btnParent + 'Products');
element.text(value);
}
I THINK this is what you need.
Also you could append both parts into one, since both are iterating over btnMain

Add existing variable to array in 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);

jQuery getting value from dynamic array

I have an array with divs ids (in my case its all divs ID values od parent div (#area) ):
jQuery.fn.getIdArray = function () {
var ret = [];
$('[id]', this).each(function () {
ret.push(this.id);
});
return ret;
};
var array = $("#area").getIdArray();
I need to get an array field value, something like this:
var lef = $("#array".[0]).css("left");
Taking a wild swing at it (see my comment on the question):
var array = $("#area").getIdArray();
var lef=$("#" + array[0]).css("left");
That assumes that getIdArray returns an array of strings, where each string is an id value for a DOM element, and that you want to get the left value for the first of those elements.
So for instance, if the array comes back as:
["foo", "bar", "charlie"]
then the selector created by "#" + array[0] is #foo, so you end up getting the left value for the foo element.
If you have an actual JS array within your variable array just use bracket notation to access each individual ID.
// I have the # before-hand since I'm assuming you have just the ID name
var lef = $('#' + array[0]) // this will access the 1st one in the array
I think you are looking for this :
var divYouWantToChange = $("#"+array[0]);
I try to formulate this as an answer because getIdArray is not a jquery function and we don't know what it does. If you'd like to apply a custom filter to the $("#area") collection you can do so using filter. This will return a jquery object where you can get the .css("left") from.
If you'd like to save both the id's and the left property you can do so with the following code:
var objects=[];
$("#area").filter(function(){
$this=$(this);//cache the object
objects.push({id:$this.attr("id"),
left:$this.css("left")
};
});
console.log(objects);

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.

jQuery list of data

I have a series of editable lists which, on a press of a button should be transformed into some sort of data structure. When it has been turned into some sort of data I need to add duplicates together.
Example:
200g banana
100g apple
200g apple
Should be turned into a data list of some sort and should in the end look like this:
200g banana
300g apple
Here's my attempt:
//button click event
$(".calculate").bind("click", function(e)
{
//get the correct parent of the button
var parent = $(this).closest("#calc");
//get relevant data
parent.find(".options").each(function(index, element)
{
var opt1 = $(this).children(".opt1").children("input").val(); //weight
var opt2 = $(this).children(".opt2").children("input").val(); //ingredient
});
});
Basically I click the button and the above script finds all the relevant data.
How can I turn this into a multidimensional array or a list of objects I can search for duplicates in?
When I try to make a dynamic object it seems to fail and when I make a multidimensional array to search in I get blocked by inArray's inability to search through them.
Problem recap:
I am able to get the user data no problem. Turning it into a list and adding together duplicates is the problem.
I will suggest you to have a global object that will contain the summary, this will look like this:
$(".calculate").bind("click", function(e)
{
var fruits = {};
//get the correct parent of the button
var parent = $(this).closest("#calc");
//get relevant data
parent.find(".options").each(function(index, element)
{
var opt1 = $(this).children(".opt1").children("input").val(); //weight
var opt2 = $(this).children(".opt2").children("input").val(); //ingredient
// here is my code
if(fruits[opt2] == undefined) {
fruits[opt2] = opt1;
} else {
// assuming that opt1 is an integer
fruits[opt2] += opt1;
}
});
// use fruits variable here
});
Here's another variant, which also does some simple parsing in case you have 100g as input, versus 100. Also, the data structure gets reinitialized every time, so everything does not get doubled on every click.
$(".calculate").bind("click", function(e)
{
//get the correct parent of the button
var parent = $(this).closest("#calc");
var ingredients = {};
var extractWeight = function (input) {
// you can add other logic here
// to parse stuff like "1kg" or "3mg"
// this assumes that everything is
// in grams and returns just the numeric
// value
return parseInt(input.substring(0, input.length - 1));
}
//get relevant data
parent.find(".options").each(function(index, element)
{
var opt1 = $(this).children(".opt1").children("input").val(); //weight
var opt2 = $(this).children(".opt2").children("input").val(); //ingredient
// initialize to 0 if not already initialized
ingredients[opt2] = ingredients[opt2] ? ingredients[opt2] : 0;
ingredients[opt2] += extractWeight(opt1);
});
});​
Here are some tips:
{} is called an object literal and is used to create a new empty object
object members can be accessed dynamically through the [] notation (i.e. if x === "name" then o[x] === o.name)
variables are visible inside functions that are at the same level or deeper in the scope - like in my example I use ingredients in the each function.
arrays in JavaScript only support numeric keys, so you won't have stuff like PHP's "associative arrays". Objects fill this gap in JS.
Here is a jsFiddle that does what you're looking for :) http://jsfiddle.net/LD9TY/
It has two inputs, one for the item name and the other for the amount. When you click add, it checks an object to see if the item was already added. If so, it increments the amount for that item based on your input. If not, it adds that item with the amount you specified. It then goes and builds a ul with all the items in your "store".
Note that this is a quick and dirty example, so there is no type checking or validation going on :)

Categories

Resources