How to create and organize a JavaScript array? - javascript

I am using ColdFusion 8 and jQuery 1.8.
I have some info coming out of a database and being populated into divs like this:
<div class='SpecInfo' data-height='10' data-width='23' data-length='156'></div>
<div class='SpecInfo' data-height='20' data-width='21' data-length='159'></div>
<div class='SpecInfo' data-height='30' data-width='25' data-length='154'></div>
<div class='SpecInfo' data-height='40' data-width='27' data-length='155'></div>
<input type='button' id='GoButton' value='Go!'>
I need to pull out that information and put it into an array and pass it to a CFC. I have a function that collects the data. It looks like this:
// SET VARS
$GoButton = $("#GoButton"),
SpecArray = {
Height: [],
Width: [],
Length: []
};
// GO
var go = function() {
var $SpecInfo = $(".SpecInfo"),
SpecInfoLen = $SpecInfo.length,
H,
W,
L;
for (i = 0; i < SpecInfoLen; i++) {
var H = $SpecInfo.eq(i).data('height'),
W = $SpecInfo.eq(i).data('width'),
L = $SpecInfo.eq(i).data('length');
// add H,W,L values to spec array
SpecArray['Height'].push(H);
SpecArray['Width'].push(W);
SpecArray['Length'].push(L);
}
// stringify spec array
// pass spec array to cfc
alert(SpecArray['Height'].length);
}
$GoButton.click(go);
What this gives me is an array of heights, an array of widths, and an array of lengths. This is not what I want. My info is organized like this
[10,20,30,40]
[23,21,25,27]
[156,159,154,155]
For each div, I want all of the attributes in a single place. I want something more like this:
[10,23,156]
[20,21,159]
[30,25,154]
[40,27,155]
What am I doing wrong? How do I organize my array?

So why do you put all the data in 3 separate arrays instead of an array of objects?
Instead of
SpecArray['Height'].push(H);
SpecArray['Width'].push(W);
SpecArray['Length'].push(L);
use
SpecArray.push( { 'height': H, 'width': W, 'length': L } );
This results in an array of objects like the following:
[
{ 'height': 10, 'width': 23, 'length': 156 },
{ 'height': 20, 'width': 21, 'length': 159 },
{ 'height': 30, 'width': 25, 'length': 154 },
{ 'height': 40, 'width': 27, 'length': 155 }
]
You have to init SpecArray as an array, though, and not as an object containing 3 arrays.

Related

In an array of named objects in javascript - are the names accessible?

If we create some objects, and fill an array with those objects, are the names stored within the array, or only the properties of the object?
I guess this may be trivial, but I haven't been able to find an answer.
var boxA = {color: "red", width: 100};
var boxB = {color: "yellow", width: 200};
var boxC = {color: "blue", width: 300};
boxArray = [boxA, boxB, boxC];
for (var i = 0; i < boxArray.length; i++) {
//****
// What code do we insert here to log
// boxA
// boxB
// boxC
//****
}
Of course, it is a trivial workaround to add
boxA.box = boxA;
etc and then call
console.log(boxArray[i].box);
But is that really necessary?
To answer your question directly - no, you can't do what you're asking. I've run into the same scenario a few times. Here's what I've done. Instead of using an array, you could just add your objects to an object literal instead, and map the object to some unique key, such as an id.
var boxes = {
boxA: { color: 'red', width: 100 },
boxB: { color: 'blue', width: 200 },
boxC: { color: 'yellow', width: 300 },
};
for (var boxKey in boxes) {
console.log(boxKey);
}
// to use
boxes.boxA; // do something with boxA
No, that does not work like that.
The variable name is a reference to an object in a heap area of memory managed by JS automatically for you.
In details it means that:
var boxA = {color: "red", width: 100};
this statement:
Creates an object in the heap
Associates a local symbol boxA with that object.
So the object is referenced by one variable yet.
var boxArray = [boxA];
here:
An array with one element is created. That element contains a reference to an object. A copy of the reference to be precise. So, the same original object is referenced twice now.
A boxArray is assigned a reference to the array, which is also placed in the heap.
To summarize: the variable names exist only in code listing for developers to easier reason about some objects in memory, instead of operating with memory addresses (which would be horrible).
Well the boxArray is filled with values of variables you are putting in it. Example:
If you would save three integer variables not the names of variables. So your new boxArray is equal to:
boxArray = [{color: "red", width: 100},{color: "yellow", width: 200},{color: "blue", width: 300}];
If you're looking to get the keys of an object try Object.keys(object)
Object.keys(boxA)
["color", "width"]
Your variable names are not accessible to the executing code, but if you need to be able to do this you can nest the objects:
var boxes = {
boxA: {
color: "red",
width: 100
},
boxB: {
color: "yellow",
width: 200
},
boxC: {
color: "blue",
width: 300
}
};
Object.keys(boxes).forEach(function(key) {
console.log(key) // boxA, boxB, boxC
console.log(boxes[key]) // {color: "red", width: 100}, etc.
});
Late to the Party but... Since ES6 javascript introduced classes. If classes is an option you could do:
class boxA { constructor() { this.color = "red"; this.width = 100; } };
class boxB { constructor() { this.color = "yellow"; this.width = 200; } };
class boxC { constructor() { this.color = "blue"; this.width = 300; } };
let boxArray = [new boxA(), new boxB(), new boxC()];
for (var i = 0; i < boxArray.length; i++) {
console.log(boxArray[i].constructor.name);
}

[possible bug]Values in array as attribute of object set to undefined

I have encountered one of the most bizzare and frustrating behaviours yet. I have sample data:
var nodes = [ //Sample data
{
ID: 1,
Chart: 1,
x: 50,
y: 50,
width: 100,
height: 80,
color: "#167ee5",
text: "Start",
label: "Start",
targets: [2]
},
{
ID: 2,
Chart: 1,
x: 500,
y: 170,
width: 100,
height: 80,
color: "#167ee5",
text: "End",
label: "End",
targets: [3]
},
{
ID: 3,
Chart: 1,
x: 270,
y: 350,
width: 100,
height: 80,
color: "#167ee5",
text: "Mid",
label: "Mid",
targets: []
}
];
for my web application. The issue is with the targets attribute. As you can see it is array. However when I do
console.log(nodes[0]);
and inspect the result in the browser it shows that the value for targets at index 0 is undefined. Same for every other targets that has some values in them (whether 1 or more).
However if I do
console.log(nodes.[0].targets);
it prints out [2]. If I do Array.isArray(nodes[0].targets) it returns false, yet if I do console.log(nodes[0]) and inspect the result in the browser console, it shows that the object prototype is in fact Array and simply the value at index 0 is undefined.
It worked the day before and now it doesn't. The only thing I did was I restructured the object that uses this variable later. But the console log is being called before the object is even instantiated for the first time (and it doesn't change the nodes var anyway, only reads it).
Does anyone have any clues as to what might be causing this behaviour. If it helps I am using Paperscript and this code runs in the paperscript scope (as it did before when everything worked fine).
UPDATE
Ok after more blind debugging I have determined the block of code that causes the issue, how or why is completely beyond me.
Basically I define an object constructor beflow. The constructor loops through the nodes, makes Paperscript shapes and adds the targets to the arbitrary data attribute of the paperJS path object:
function Flowchart(nodes, chartdata) {
//Member vars. They are only used internally
var connections = [];
var shapes = [];
var connectors = [];
//Constructor operations
createShapes(nodes); //If I uncomment this, the problem goes away
//...
function createShapes(nodes) {
nodes.forEach(function (node) { //for each node data entry
console.log(node); //At this point, the targets are screwed up already
var point = new Point(node.x, node.y); //make a PaperJS point for placement
var size = new Size(node.width, node.height); //make a PaperJS size object
var shape = makeRectangle(point, size, 8, node.color); //Pass to the object instantiating function
shape.data = { //Store arbitrary data for programming reference.
ID: node.ID,
label: node.label,
text: node.text,
'connectors': {
to: [],
from: []
},
targets: node.targets //this is undefined
};
console.log(node.targets) //this logs [2] or [3] but not Array[1]...
shapes.push(shape); //Store reference for later
});
shapes.forEach(function (shape) { //loop though all drawn objects
if (shape.data.targets.length > 0) { //if shape has targets
var targets = _.filter(this.shapes, function (target) {
return _.contains(shape.data.targets, target.data.ID);
});
for (var i = 0; i < shape.data.targets.length; i++) {
shape.data.targets[i] = targets[i]; //Replace the ID-type reference with drawn object reference
}
}
});
}
//... The rest of the object
}
console.log(nodes);
//It doesnt seem to matter whether i put this before or after instantiating.
//It doesnt even matter IF I instantiate in the first place.
var chart = new Flowchart(nodes, chartdata);
This behaviour has been caused by the changes to how Chrome treats enumerable properties of objects. Because Chrome updates silently, it's impossible to notice.
It must have been causing me a lot of headache if I remembered the cause after all this time... (Also it's embarrassing how bad I was at writing questions, but I guess that I realise it means I have progressed since then somewhat).

rChartsCalendar: Setting programmatically the nested json attributes to configure the calendar chart

The standard example of the rChartsCalendar works with defaults of the JS calendar as shown in http://kamisama.github.io/cal-heatmap/
The example code below works fine:
dat <- read.csv('http://t.co/mN2RgcyQFc')[,c('date', 'pts')]
library(rChartsCalendar)
r1 <- plotCalMap(x = 'date', y = 'pts',
data = dat,
domain = 'month',
start = "2012-10-27",
legend = seq(10, 50, 10),
itemName = 'point',
range = 7
)
The problem comes when I try to set nested attributes in R, for example to define the position and the offset of the label. In HTML / JS it would be as easy as writing following code, but how can I define from R the values for the offset for the label?
var cal = new CalHeatMap();
cal.init({
itemSelector: "#label-d",
domain: "day",
range: 2,
displayLegend: false,
label: {
position: "right",
width: 46,
offset: {x: 10, y: 30}
}
});
I tried using the method set and passing the json piece as string, but then it gets rendered with the quotes in HTML/JS, which obviously doesn't work
r1$set(label="{position: 'left', width: 110, offset: { x: 20, y: 12 } }")
Update: I got it working using a combination of "c" and "list" as follows:
label= c( list(position = 'left'),list( width = 110),list(offset = list (x=20,y=30))),
It's not very straight away, but I felt like sharing it because it took me a lot of time

JavaScript object with couple of parameters

The goal
I want to create a function which have couples of parameters like that:
MyObject.calculateResponsiveHeights({
containers: {
".content",
".sidebar"
},
spacing: {
125, // This will be attributed to ".content"
240 // This will be attributed to ".sidebar"
}
});
The problem
I do not how I can do this.
What I have now (the function implementation — just to be aware of the situation)
function calculateResponsiveMeasures() {
var containerContentResponsiveHeight = $(window).height() - 185,
sidebarProductsSummaryResponsiveHeight = $(window).height() - 255;
containerContentResponsiveHeight = containerContentResponsiveHeight + "px";
sidebarProductsSummaryResponsiveHeight = sidebarProductsSummaryResponsiveHeight + "px";
$(".container-content").css("height", containerContentResponsiveHeight);
$(".products-summary").css("height", sidebarProductsSummaryResponsiveHeight);
}
Yeah, that's disgusting, huh?
Observations
I'm not asking to improve my code, nor say whether it is better or worse way to do — I just want to better organize my function.
Cheers!
You're trying to create an array: [1, 2, 3].
However, you should use a single object instead:
{
".content": 125,
".sidebar": 240
}
You can then iterate over the properties using a for in loop.

Return value from largest object property in array - JS

The title of this question might be a little misleading, but it was the closest to accurately describe the problem I was having.
I am currently working on a custom lightbox script, similar to the one that can be found on Facebook and airbnb. Once the user clicks on an image, the lightbox is not resized to the content, rather the image is centered with a black area around it (if you're a regular FB user, you should know what I mean).
I am storing the images to be used for the lightbox in an JS array as follows (generated from a MySQL database:
var item_images = [
{ 'id': 2, 'url': '50929ab7ae8e5.jpg', 'caption': 'My Photo # 1', 'width': 1000, 'height': 750 },
{ 'id': 7, 'url': '50929ab7ae8e8.jpg', 'caption': 'My Photo # 1', 'width': 1000, 'height': 800 },
{ 'id': 3, 'url': '50929ac161d10.jpg', 'caption': 'My Photo # 2', 'width': 1000, 'height': 750 },
{ 'id': 4, 'url': '50929acbe8dc8.jpg', 'caption': 'My Photo # 3', 'width': 1000, 'height': 750 }
];
I need a function in JS to find the largest width and largest height required for the images. For example, given the data above, I'd like a function GetMaxSizes() which will return 800 (largest height in the array) and 1000 (the largest width in the array).
Is there a more efficient way than looping over the entire array and comparing everything? My concern is this will become slow if there are lots of elements inside item_images:
function GetRequiredHeight()
{
var req_height = 0,
req_width = 0;
for(var i in item_images)
{
var image = item_images[i];
if(image.width > req_width) { req_width = image.width };
if(image.height > req_height) { req_height = image.height };
}
return { width: req_width, height: req_height };
}
This is O(n) complexity, and I can't imagine anything better than that. Iteration through array having 10000 elements is not a big deal for many many years. How many pics would you like to store here? Milions? If your algorithm slows down, I would search for different reasons.
I assume you do this iteration once. If you want to alter this array frequently, some optimizations could be done to avoid traversing whole array whole the time. I have some good idea but it's more writing, so if you need it please comment this answer.

Categories

Resources