create multidimensional array or object in jquery each loop - javascript

this is what I've got and been struggeling for hours. if I alert(i)in the each loop it gives me 1,2,3... but if I want to use as as key for a multidimensional array it is like a string "i"
$(document).ready(function(){
var positions=[];
$( ".box" ).each(function(i) {
//alert(i);
var elPositions = {};
elPositions.i = $(this).offset().top;
positions.push(elPositions);
//$elPosArray[i] = $(this).offset().top;
//$(this).html('outer height--> ' + $(this).outerHeight(true));
});
console.log(positions);
//console.log(el);
});
There are Questions and answers to this topic but none of them helped me to get this to work.
I would like to get an array or obj looking something like:
positions[0]['offset'] = '120';
positions[0]['height'] = '300';
positions[1]['offset'] = '420';
positions[1]['height'] = '180';
positions[2]['offset'] = '600';
positions[2]['height'] = '100';
positions[3]['offset'] = '700';
positions[3]['height'] = '300';
Here is a fiddle with the html http://jsfiddle.net/Z9WrG/

You're pretty much there!
In your loop, elPositions (here renamed data) is recreated new on each iteration, and then pushed into the array with a consecutive index. There's no need to specify i in the data object as i is assigned automatically when you push into the array.
See updated fiddle: http://jsfiddle.net/Z9WrG/2/
and code:
$(document).ready(function(){
var positions=[];
$( ".box" ).each(function() {
var $this = $(this);
var data = {};
data.offset = $this.offset().top;
data.height = $this.height();
positions.push(data);
// Now, positions[iteration_index] = { offset: x, height: y }
});
console.log(positions);
console.log(positions[0].height);
console.log(positions[0].offset);
});

Related

Javascript stored only the last one from a loop in an JSON Object

I have a HTML Site with 4 inputRange slidern. If a user click on a button all the values from the ranges should be stored in a nested JSON Object. So far so good, but JS only saves the last one in that Array and not the others before.
But all Sliders have different values from 1 to 5, but JS saves only the 4 from the last slider. Here's my code:
//Speichert die aktuellen Angaben in einem Nested-JSON Objekt
function saveBewertung() {
var jsonObj = {};
var kriterien = [];
var bewertungen = {};
//Loop
$('input[type=range]').each(function() {
var id = $(this).attr("id");
var note = $(this).val();
bewertungen.id = id;
bewertungen.note = note;
kriterien.push(bewertungen);
jsonObj.Bewertungen = kriterien;
});
jsonObj.Kommentar = $('textarea#kommentar').val();
//TEST AUSGABE
alert(JSON.stringify(jsonObj));
}
Result:
You are pushing the same object to the array again and again. You need to initialize bewertungen every time in the each block.
Declare
var bewertungen = {};
inside the each block
$('input[type=range]').each(function() {
var bewertungen = {};
var id = $(this).attr("id");
var note = $(this).val();
bewertungen.id = id;
bewertungen.note = note;
kriterien.push(bewertungen);
});
jsonObj.Bewertungen = kriterien; //this line can be moved out
Another possibility next to the solution from #gurvinder372 is to shorten the function so you don't need to declare the variables bewertungen, id and note:
//Speichert die aktuellen Angaben in einem Nested-JSON Objekt
function saveBewertung() {
var jsonObj = {};
var kriterien = [];
//Loop
$('input[type=range]').each(function() {
// Anonymous object
kriterien.push({
id: $(this).attr("id"),
note: $(this).val()
});
});
jsonObj.Bewertungen = kriterien;
jsonObj.Kommentar = $('textarea#kommentar').val();
//TEST AUSGABE
alert(JSON.stringify(jsonObj));
}
Here is some description how this thing is working
var bewertungen = {}; // this line declare the object this object will hold values in each loop.
$('input[type=range]').each(function() {
var bewertungen = {};
var id = $(this).attr("id");
var note = $(this).val();
bewertungen.id = id; // this line add value to {bewertungen} object key
bewertungen.note = note; // this line add value to {bewertungen} object key
kriterien.push(bewertungen); // every itration will push value to [kriterien] array
});
jsonObj.Bewertungen = kriterien; // this is final array with all values

JSON Split - Place array text into li during interval

My task is to take the 3 different color lists in the jsonObj and place them into a <ul>. They should only appear one at a time, every second. For the sake of the fiddle, I put it to every 5 seconds.
I haven't gotten to the 2nd or 3rd list of colors yet because while I can list out my 1st color list, they're appending outside of the listItem I've created for them. The code it spits it is:
var jsonObj = '{"one":["red","green","blue"], "two":["red","green","blue"], "three":["orange","purple","hotpink"]}',
object = JSON.parse(jsonObj),
cOne = object.one,
cTwo = object.two,
cThree = object.three,
i = 0,
timer;
$('body').append('<ul/>');
timer = setInterval(function() {
$.each(cOne, function() {
var list = $('body ul'),
listItem = $(list).append('<li>'),
html = $(listItem).append(cOne[i]);
if (i < cOne.length) {
i++;
$(cOne[i]).split("");
list.append(html);
} else if (i = cOne.length) {
i = 0;
}
});
}, 5 * 1000);
timer;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Also available at https://jsfiddle.net/ep76ba3u/
What it does:
<ul>
<li></li>
"red"
<li></li>
"blue"
</ul>
What it should look like:
<ul>
<li>red</li>
<li>blue</li>
</ul>
I've tried rearranging it all. I've tried using wrap, innerWrap. I've tried just using text() and a few other methods. I started working on it at 3am and its 5am now... brain is fried. Any idea how to get this moving is appreciated.
You can not append partial html, that's why this $(list).append('<li>') is immediately closing the <li>.
And you should not modify the markup in a loop. It's obnoxious and unperformant.
Check out this approach to your code:
var jsonObj = '{"one":["red","green","blue"], "two":["red","green","blue"], "three":["orange","purple","hotpink"]}',
object = JSON.parse(jsonObj),
iteration = 0,
timer;
$('body').append('<div id=container>');
//a few utilities, because I don't want to repeat myself all over the place:
var string = value => value == null ? "" : String(value);
var wrapInNode = nodeName => value => `<${nodeName}>${ string(value) }</${nodeName}>`;
//here I create a few utility-methods that will build my markup:
var li = wrapInNode('li');
var ul = wrapInNode('ul');
var header = wrapInNode('h4');
timer = setInterval(function() {
//building the complete markup and adding it at once
var blocks = [],
//how many rows should I show in this iteration
numRowsLeft = ++iteration,
//getting this result is just a nice sideeffect of using `every()` instead of `forEach()`
//to short-curcuit the loop
done = Object.keys(object)
.every(function(key) {
//this line makes the title to be added with as a distinct iteration and not with the first item,
//check out what happens when you remove it
--numRowsLeft;
var rows = object[key]
//shorten the Array to numRowsLeft, if necessary
.slice(0, numRowsLeft)
//wrap each item in a li-node with my predefined utility-function
.map(li);
numRowsLeft -= rows.length;
//building the markup for this block
blocks.push(header(key) + ul(rows.join("")));
//here I'm short circuiting the loop. to stop processing the other keys on Object
return numRowsLeft > 0;
});
$('#container').html(blocks.join(""));
if (done) {
clearInterval(timer);
}
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
And showing the header all the time while only adding the points:
var jsonObj = '{"one":["red","green","blue"], "two":["red","green","blue"], "three":["orange","purple","hotpink"]}',
object = JSON.parse(jsonObj),
iteration = 0,
timer;
$('body').append('<div id=container>');
var string = value => value == null ? "" : String(value);
var wrapInNode = nodeName => value => `<${nodeName}>${ string(value) }</${nodeName}>`;
var li = wrapInNode('li');
var ul = wrapInNode('ul');
var header = wrapInNode('h4');
timer = setInterval(function() {
var numRowsLeft = ++iteration,
blocks = Object.keys(object)
.map(function(key) {
var rows = object[key]
.slice(0, numRowsLeft)
.map(li);
numRowsLeft -= rows.length;
return markup = header(key) + ul(rows.join(""));
});
$('#container').html(blocks.join(""));
// If I'd had room to show even more rows, then I' done
if (numRowsLeft > 0) {
clearInterval(timer);
}
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
I feel compelled to put in an answer which should perform better by cache of the jQuery objects and processes the objects and each color in them, hitting DOM once for each color.
var jsonObj = '{"one":["red","green","blue"], "two":["red","cyan","darkblue"], "three":["orange","purple","hotpink"]}',
objects = JSON.parse(jsonObj);
// set timer values
var basetime = 1000;
var delaytime = basetime;
// cache the ul list
var myul = $('<ul/>').appendTo('body');
//process outer objects
$.each(objects, function(key, item) {
// process color array held in item
$.each(item, function(index, color) {
setTimeout(function() {
$('<li/>').text(color).css('color', color).appendTo(myul);
}, delaytime);
delaytime = delaytime + basetime;
});
});
Test it out here https://jsfiddle.net/MarkSchultheiss/yb1w3o73/
var jsonObj = '{"one":["red","green","blue"], "two":["red","green","blue"], "three":["orange","purple","hotpink"]}',
object = JSON.parse(jsonObj),
cOne = object.one,
cTwo = object.two,
cThree = object.three,
i = 0,
timer;
$('body').append('<ul>');
var i = 0;
timer = setInterval(function() {
if (i === cOne.length - 1) clearInterval(timer);
$('body ul').append('<li>');
$('body ul li').last().text(cOne[i]);
i++;
}, 1000);

variable array duplicating / skipping one item when writing

var dates =["09/27/2014","12/19/2013","01/13/2015",""];
var departments = ["Item1","Item2","item3",""];
var writespeed = 400;
$('.department_name').html(departments[fade-1]);
$('.date_name').html(dates[fade-1]);
The issue is in the following line of code:
$('.department_name').html(departments[fade-1]);
The issue is that in your loop, "fade", is not incremented. You can either use fade++ or assign it to a different variable and increment it.
Nothing but assigning a new variable worked.
var z = 1;
and then:
z++;
Its hard to tell from just the jquery, but I believe 'fade' needs to be incremented:
var fade = 1;
var depart_time = 1000;
console.log(0,fade);
$('.shutter').removeClass('closed-shutter open-move opened-shutter close-move');
function writeText(args) {
var dates =["09/27/2014","04/26/2014","03/17/2015"];
var departments = ["Item1","Item2","Item3"];
var writespeed = 700;
$('.write-text').each(function(){
$('.department_name').html(departments[fade-1]);
$('.date_name').html(dates[fade-1]);
fade++;
$(this).width('auto');
var w = $(this).width();
$(this).width(0).animate({width:w+'px'}, writespeed, function(){
if ($(this).hasClass('patient_name')) {
$(this).removeClass('write-text');
}
});
});
}

How to get value from object?

I have this code which works.
$(document).ready(function(){
$('form').live('submit', function(){
// have to do it like this to simulate my problem
var aform = $(this);
var dat = { "TITLE" : "55h5", "OWNER" : "fff" };
$('#template').tmpl(dat).prependTo('#content');
return false;
});
});
But what I would like is to take the values from aform and insert them directly into
$('#template').tmpl( HERE ).prependTo('#content');
The data from the form have do accessed through aform to simulate my problem. Can this be done?
Here is the problem illustrated
http://jsfiddle.net/HYLYq/
You could use .serializeArray(), and then loop over it to create the right data structure:
var data = {},
values = $(this).serializeArray();
for(var i = values.length; i--;) {
data[values[i].name] = values[i].value;
}
You could do the same with plain JavaScript (is probably faster):
var elements = $(this)[0].elements,
data = {};
for(var i = elements.length; i--;) {
data[values[i].name] = values[i].value;
}

Get Next and Previous Elements in JavaScript array

I have a large array, with non-sequential IDs, that looks something like this:
PhotoList[89725] = new Array();
PhotoList[89725]['ImageID'] = '89725';
PhotoList[89725]['ImageSize'] = '123';
PhotoList[89726] = new Array();
PhotoList[89726]['ImageID'] = '89726';
PhotoList[89726]['ImageSize'] = '234';
PhotoList[89727] = new Array();
PhotoList[89727]['ImageID'] = '89727';
PhotoList[89727]['ImageSize'] = '345';
Etc....
I'm trying to figure out, given an ID, how can I can get the next and previous ID... So that I could do something like this:
<div id="current">Showing You ID: 89726 Size: 234</div>
Get Prev Get Next
Obviously, if we're at the end or beginning of the array we just a message...
Why don't you add properties 'Prev' & 'Next' to that array?
PhotoList[89725] = new Array();
PhotoList[89725]['Prev'] = 89724;
PhotoList[89725]['Next'] = 89726;
PhotoList[89725]['ImageID'] = '89725';
PhotoList[89725]['ImageSize'] = '123';
This is just 'doubly-linked list' data structure.
Based on your example the IDs are sequential...
This is another way of writing your example. new Array() really isn't what you should be using because those are objects you are creating. Also, I left the numbers as strings, but I'm not sure why you would want to do that. You could add next and prev like kuy suggested
PhotoList[89725] = {ImageID: '89725',
ImageSize: '123'};
PhotoList[89725] = {ImageID: '89726',
ImageSize: '234',
Next: '89727',
Prev: '89725'};
PhotoList[89725] = {ImageID: '89727',
ImageSize: '345'};
All of these are accessible just like your other structure.
There's really no way other than to iterate through the possible ids sequentially until you find one which has an entry in your array. For example:
function findClosest(arr, id, increasing) {
var step = increasing ? 1 : -1;
for(var i=id+step; i>=0 && i<=max_id; i+=step)
if( arr[id] )
return id;
}
Obviously, this approach requires that you keep track of the max_id so that you don't iterate forever; here I assume that it's a global variable, but you might want to make it a parameter to the findClosest function. You'd call this function like so:
var prev = findClosest(arr, id, false);
var next = findClosest(arr, id, true);
I agree with the rest quotes you should be using objects not an array. Also make sure you create new arrays using the literal notation and not the new keyword with built in types. The new keyword is bad news and you could clobber the global object. Check out JSLint.
var a = new Array(); //bad dont use
var a = []; //this is the best way to create a new array
var o = {}; //create new objects like this
As for the problem at hand. Why not write a simple container that has its own internal counter?
function PhotoListContainer(PhotoList)
{
if(PhotoList === undefined)
throw("no photo list");
this.counter = 0;
var self = this;
this.current = function(){
return PhotoList[self.counter];
};
this.next = function(){
return PhotoList[self.counter + 1];
};
this.prev = function(){
return PhotoList[self.counter - 1];
};
// You could even write a function that loops each value from the current counter :)
this.each_from_counter = function(callback){
for(var i = self.counter; i < PhotoList.length; i++)
{
callback(PhotoList[i], i);
self.counter++;
}
};
}
//use
var pc = new PhotoListContainer(PhotoList);
pc.counter = 500;
pc.next(); //returns the 501st object
pc.prev(); //returns the 499th object
pc.each_from_counter(function(photo, index){
photo.somehting;
});
No arrays at all are better..
images = {
0: {
size: 12345, /* dont realy need as you can use JS to mesure the size. */
title: "day 1 on holiday"
},
1: {
size: 13549, /* dont realy need as you can use JS to mesure the size. */
title: "day 2 on holiday"
},
2: {
size: 16548, /* dont realy need as you can use JS to mesure the size. */
title: "day 3 on holiday"
},
}
for(x in images){
/* x = "the id of the image." */
url[] = "/images/" + x + ".png";
title[] = images[x].title;
size[] = images[x].size;
console.log("File: " + url[x] + " , Title: " + title[x] + " , Size: " + size + "bytes")
}
var sibNum = 0;
var sibList = [];
var prevSiblingID = false;
for (n in w) {
sibNum++;
sibList[n] = {
title : n,
prevSiblingID : prevSiblingID
};
if (prevSiblingID) {
sibList[prevSiblingID].nextSiblingID = n;
}
prevSiblingID = n;
};
sibList[prevSiblingID].nextSiblingID = false;
you can use grep function and calculate prev or next item of specified array:
object = $.grep(data, function(e) {
if(e.id == yourId) {
return data[data.indexOf(e) + 1]; // or -1 for prev item
}
});
i think your image list will come from DB so you may can try this code, this code is working for me.
<?
$prev="";
$next="";
$cur=0;
$i=0;
$pid=$_GET['pid'];
while($rowcon=mysql_fetch_assoc($result))
{
$arr[$i]=$rowcon['pid'];
if($rowcon['pid']==$pid)
{
$cur=$i;
}
$i++;
}
if($cur<$num_rows)
$next=$arr[$cur+1];
else
$next="";
if($cur>0)
$prev=$arr[$cur-1];
else
$prev="";
echo $prev." ".$cur." ".$next;
?>

Categories