Strange behavior for jQuery push() into array - javascript

I'm trying to push some elements into a 2d array
The code I am using is:
samount.push ({
"value": val,
"currency": currency
});
The array that I am trying to push into samount is like this:
groupedArray =
[{value: 100, currency: 'EUR'},
{value: 100, currency: 'EUR'},
{value: 100, currencu: 'EUR'}]
In fact, the array above represents rows of one table, and at each row click, the push() function is adding do samount array a new element
After 2 row clicks, the samount array looks like:
samount =
[{value: 100, currency: 'EUR'},
{value: 100, currency: 'EUR'}]
At the third row click, the array becomes:
samount =
[{value: 200, currency: 'EUR'},
{value: 100, currency: 'EUR'},
{value: 100, currencu: 'EUR'}]
I have to mention that my code has no sum inside, so it is very strange that the push() function is summing the values of first element and still is adding them to the array
Do you know if the push() function is ok for adding element to this type of arrays?
The complete code is:
"fnDrawCallback": function (oSettings) {
var $dt = $('#dt_debts').footable({
breakpoints: { // The different screen resolution breakpoints
phone: 320,
tablet: 768
}
});
$dt.trigger('footable_resize');
var amount = new Array();
var samount = new Array();
$('#dt_debts tbody tr ').each( function () {
var iPos = oTable.fnGetPosition( this );
if (iPos!=null) {
var aData = oTable.fnGetData( iPos );
if (jQuery.inArray(aData[0], selected)!=-1) {
$(this).addClass('row_selected');
$(this).find( 'td input:checkbox' ).attr('checked', 'checked');
}
}
$(this).click( function (e) {
e.preventDefault();
var iPos = oTable.fnGetPosition( this );
var aData = oTable.fnGetData( iPos );
var iId = aData[0];
is_in_array = jQuery.inArray(iId, selected);
if (is_in_array==-1) {
selected[selected.length]=iId;
}
else {
selected = jQuery.grep(selected, function(value) {
return value != iId;
});
}
if ( $(this).hasClass('row_selected') ) {
console.info('>>> Operatie de eliminare');
$(this).removeClass('row_selected');
$(this).find( 'td input:checkbox' ).prop('checked', false);
if ($(aData[0]).data('typo') == "t-0") {
val = parseFloat(aData[9].split(" ")[0]);
currency = aData[9].split(" ")[1];
if (currency != '') {
$.each(amount, function(idx, item) {
if (item.currency == currency && item.value == val) {
amount.splice(idx, 1); // Remove current item
return false; // End the loop
}
});
}
} else if ($(aData[0]).data('typo') == "t-1") {
val = parseFloat(aData[10].split(" ")[0]);
currency = aData[10].split(" ")[1];
if (currency != '') {
$.each(samount, function(idx, item) {
if (item.currency == currency && item.value == val) {
samount.splice(idx, 1); // Remove current item
return false; // End the loop
}
});
}
}
console.info(amount);
console.info(samount);
} else {
console.info('>>> Operatie de adaugare');
$(this).addClass('row_selected');
$(this).find( 'td input:checkbox' ).attr('checked', 'checked');
if ($(aData[0]).data('typo') == "t-0") {
val = parseFloat(aData[9].split(" ")[0]);
currency = aData[9].split(" ")[1];
if (currency != '') {
amount.push ({
"value": val,
"currency": currency
});
}
} else if ($(aData[0]).data('typo') == "t-1") {
val = parseFloat(aData[10].split(" ")[0]);
currency = aData[10].split(" ")[1];
if (currency != '') {
samount.push ({
"value": val,
"currency": currency
});
}
}
console.info(amount);
console.info(samount);
}
}
Aftre spending hours of searching the error, I have figured that the error is in this part of code:
var objects1 = new Array();
objects1 = samount;
var categories1 = new Array();
var groupedObjects1 = [];
var i = 0;
_.each(objects1,function(obj){
var existingObj;
if($.inArray(obj.currency,categories1) >= 0) {
existingObj = _.find(objects1,function(o){return o.currency === obj.currency;});
existingObj.value += obj.value;
} else {
groupedObjects1[i] = obj;
categories1[i] = obj.currency;
i++;
}
});// JavaScript Document
Actually it seems that the samount array is beeing modified even if I have declared a new array for using into loop. I do not understand why the loop is modifying the initial array, even if I am not using it

Yes, push is fine. Indeed I tested it and it works as it is supposed to. What I assume is happening is the value being modified somewhere else - since you are pushing an object into the array with the value val the array would only hold a reference to the entire thing not the values it represents.
Just to illustrate this
var val = { "value" : 100 };
var storage = [ ];
storage.push(val);
console.log("value : " + val.value);
console.log("value in storage : " + storage[0]["value"]);
val.value = 200;
console.log("value : " + val.value);
console.log("value in storage : " + storage[0]["value"])
yields
value : 100
value in storage : 100
value : 200
value in storage : 200
The variables in JavaScript are pass by value for primitives (e.g., integers) but pass by reference for objects.

You can use .join() instead of .push()
//if you want the ful array as a single element:
groupedArray =
[{{value: 100, currency: 'EUR'},
{value: 100, currency: 'EUR'},
{value: 100, currencu: 'EUR'}}];
samount.join(groupedArray);
//if you want each element in groupedArray as elements in samount:
groupedArray =
[{value: 100, currency: 'EUR'},
{value: 100, currency: 'EUR'},
{value: 100, currencu: 'EUR'}];
samount.join(groupedArray);

Related

JSON array filter does not apply

I am trying to filter the data from an array, but it is throwing an error saying
filter() is not function
Here is the code:
var selectedObject = [];
selectedObject= JSON.stringify(formsDataSource.data());
//console.log(selectedObject);
//var filtered = $.grep(selectedObject, function (el) {
// return el.po_order_no = 18;
//});
//console.log((filtered));
if (selectedObject == undefined) {
alert("Undefined");
} else {
var data= selectedObject.filter(function (element) { return element.po_order_no = "18"; })
alert("" + data);
}
I tried many things but it is still throwing an error. Any help?
Few observations :
selectedObject= JSON.stringify(formsDataSource.data());
This statement states that selectedObject is a string. A string does not have a filter() method.
condition inside filter function should be element.po_order_no == "18" instead of element.po_order_no = "18"
Solution :
var selectedObject = [
{
"po_order_no": 18,
"po_order_name": "abc"
},
{
"po_order_no": 19,
"po_order_name": "xyz"
}
];
if (selectedObject == undefined) {
console.log("Undefined");
} else {
var data = selectedObject.filter(element => element.po_order_no == "18")
console.log(data);
}

Javascript Object: find a key/value when in range

i have a Javascript object like this one:
pItems = {
single : {
...
plz: {
"1000": 12,
"2000-2500" : 40
"3000": 30
}
...
}
}
i get a value from an inputfield e.g. "2300" and now i need the value for this "2300" from the object. Because 2300 is in the range of the plz-key "2000-2500" the value i should get back is "40".
i have no clue atm how i could find the right value, if i am looking up something in key "ranges".
thank you for any advice, help with that.
You can iterate over the keys, split them, if possible and perform a check. If in range, then return the item and leave the loop.
function getItem(value) {
var item;
Object.keys(object.plz).some(function (k) {
var part = k.split('-');
if (+value >= part[0] && +value <= (part[1] || part[0])) {
item = object.plz[k];
return true;
}
});
return item;
}
var object = { plz: { "1000": 12, "2000-2500": 40, "3000": 30 } };
console.log(getItem('1000'));
console.log(getItem('2300'));
var pItems = {
single : {
plz: {
"1000": 12,
"2000-2500" : 40,
"3000": 30
}
}
};
var val =2300 ;
$.each(pItems.single.plz, function(k,v) {
var min = parseInt(k.split('-')[0]);
var max = parseInt(k.split('-')[1]);
if(isNaN(max) ){
if(min == val){
console.log(v);
return;
}
}else if(val>=min || val <= max){
console.log(v);
return;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
Wraped as function:
function getValue(search) {
for( var range in pItems.plz ) {
var split = range.split("-");
if( search >= parseInt(split[0]) && search <= parseInt(split[1] || split[0]) )
return pItems.plz[range];
}
}
Call:
console.log(getValue(1000)); // 12
console.log(getValue(2300)); // 40
console.log(getValue(3000)); // 30
console.log(getValue(5000)); // undefined

Json data reading through Javascript

I am trying to read json data from website through JavaScript. Json looks like this:
{
"status" : "success",
"prices" : [
{
"market_hash_name" : "AK-47 | Aquamarine Revenge (Battle-Scarred)",
"price" : "11.38",
"created_at" : 1460116654
},
So, I got code:
if(pricelist.prices.market_hash_name == itemName) {
var price2 = Math.round(Number(pricelist.prices.market_hash_name[itemName].price) * 1000);
I know that I am doing something wrong here, could someone help me out?
EDIT: That Function is here:
function loadItems() {
$("#refresh-button").remove();
$("#loading").addClass("active");
$.getJSON("" + bot_sids[cur_bot], function(data) {
if (data.success) {
var i = 0;
var ready = true;
var invIndexes = [];
for (var index in data.rgInventory) {
invIndexes[i] = index;
i++;
}
i = 0;
$.getJSON("", function(pricelist) {
apricething = pricelist;
if (pricelist.status) {
for (id = 0; id < invIndexes.length; id++) {
var index = invIndexes[id];
var item = data.rgDescriptions[data.rgInventory[index].classid + "_" + data.rgInventory[index].instanceid];
if (item.tradable != 1) {
continue;
}
var itemName = item.market_hash_name;
var iconUrl = item.icon_url;
console.log(itemName);
for(i=0; i<pricelist.prices.length; i++){
if (pricelist.prices[i].market_hash_name == itemName) {
var price2 = Math.round(Number(pricelist.prices[i].market_hash_name.price) * 1000);
console.log(itemName);
console.log(price2);
if (price2 >= 1) {
prices2[itemName] = price2;
items[id] = {
name: itemName,
price: price2,
iconurl: iconUrl,
classid: data.rgInventory[index].classid,
id: index,
done: true
};
} else {
items[id] = {
done: true
};
}
} else {
items[id] = {
name: itemName,
price: 0,
iconurl: iconUrl,
classid: data.rgInventory[index].classid,
id: index,
done: false
};
}
}
}
finishedLoading();
}
});
According to your data structure, you need an iteration over prices.
var price2;
pricelist.prices.some(function (item) {
if (item.market_hash_name == itemName) {
price2 = Math.round(Number(item.price) * 1000);
return true;
}
});
Try this :
if(pricelist.prices[0].market_hash_name == itemName) {
var price2 = Math.round(Number(pricelist.prices[0].market_hash_name.price) * 1000);
Your mixing some things up here. prices is an array, but you are not accessing the elements of the array, but the whole array.
Then in the number calculation, you are trying to access market_hash_name as an array, which is a string.
So the following code will walk through your prices and calculate price2 if the names match.
for(var i=0; i<pricelist.prices.length; i++){
if (pricelist.prices[i].market_hash_name === itemName) {
var price2 = Math.round(Number(pricelist.prices[i].price) * 1000);
}
}

How to I compare an input value to reference values in an object literal?

I'd like to compare a user input value, to a set of values arranged in an object literal. The user will input two values, a reference variable wk and a number. Those need to be cross referenced in the object literal, but I can't seem to figure out the logic to do so?
The object literal is constructed as follows:
var reference = {
wk31: {
_90th: '758',
_75th: '683',
_50th: '600',
_25th: '516',
_10th: '441'
},
wk32: {
_90th: '815',
_75th: '734',
_50th: '644',
_25th: '554',
_10th: '472'
},
wk33: {
_90th: '870',
_75th: '783',
_50th: '687',
_25th: '590',
_10th: '503'
}
}
For example, if
wk = 32 & number = 755, then I'd like to make the user aware that their number is between the 75th and 90th percentile for that wk value.
Any help is appreciated. Thanks.
From what is written here and here, it appears you cannot rely on the order of the array returned by Object.keys() and the order in which the for ... in loop will enumerate over an object's properties.
Instead, rearrange the data into something that is more usable.
First, get the correct object for the wk value using the following:
var wkObj = reference['wk' + wk];
Then rearrange those values using:
var percentiles = $.map(wkObj, function(value, key) {
return { number: Number(value), percentile: key.substr(1) };
}).sort(function(a, b) { return a.number - b.number; });
This creates an array of objects, where each object has two properties: (1) number, which is a number, and (2) percentile, which is a string. The array is sorted by the number values in ascending order.
For example, the percentiles array would look like the following for wk = 32:
[
{ number: 472, percentile: '10th' },
{ number: 554, percentile: '25th' },
{ number: 644, percentile: '50th' },
{ number: 734, percentile: '75th' },
{ number: 815, percentile: '90th' }
]
Now the number values are numbers, not strings, and you can safely loop through the array in the desired order.
var upperIndex = -1;
$.each(percentiles, function(i, obj) {
if (obj.number > number) {
upperIndex = i;
return false;
}
});
Here is a jsfiddle that shows the code above in use.
var reference = {
wk31: {
_90th: '758',
_75th: '683',
_50th: '600',
_25th: '516',
_10th: '441'
},
wk32: {
_90th: '815',
_75th: '734',
_50th: '644',
_25th: '554',
_10th: '472'
},
wk33: {
_90th: '870',
_75th: '783',
_50th: '687',
_25th: '590',
_10th: '503'
}
}
function checkReference()
{
var input = "wk" + document.querySelector("#week_input").value;
var perc = document.querySelector("#numberInput").value;
var obj = reference[input];
var keys = Object.keys(obj);
var string = "";
for (var i = 0; i < keys.length; i++)
{
if (perc > obj[keys[i]])
{
if (i == 0)
{
string = "number higher than 90th percentile for that wk value.";
break;
}
else
{
string = "number is between "+keys[i].substr(1)+" and "+ keys[i-1].substr(1) +" percentile for that wk value.";
break;
}
}
else if (perc < obj[keys[i]] && i == keys.length-1)
{
string = "number lower than 10th percentile for that wk value.";
}
}
alert(string);
}
document.querySelector("#doCheck").addEventListener("click", checkReference, false);
<input id="week_input" type="range" min="31" max="33">
<input id="numberInput" type="range" min="0" max="1000"><br />
<button id="doCheck">Check</button>
Something like this:
User slides the values into place. The code checks the object and returns the value. The sliders are used to greatly reduce user input errors.
HTML
<div id="result"></div>
JS
var reference = {
wk31: {
_90th: '758',
_75th: '683',
_50th: '600',
_25th: '516',
_10th: '441'
},
wk32: {
_90th: '815',
_75th: '734',
_50th: '644',
_25th: '554',
_10th: '472'
},
wk33: {
_90th: '870',
_75th: '783',
_50th: '687',
_25th: '590',
_10th: '503'
}
}
var result = $("#result");
//wk value
var bracket = 32;
//value to factor into percentile
var value = 740;
var percentileResult = "";
for (var i in reference) {
if (reference.hasOwnProperty(i) && i.indexOf("wk" + bracket) !== -1) {
var ref = reference[i];
for (var j in ref) {
if (ref.hasOwnProperty(j)) {
var percentileValue = ref[j];
if (percentileValue < value) {
percentileResult = j;
break;
}
}
}
}
};
result.html(value + " is in the " + percentileResult.replace("_", "") + " percentile of wk" + bracket);
Fiddle:
http://jsfiddle.net/7avjhvsy/
Consider adding the following code snippets before the loop and inside the first loop's if statement respectively if you might have wk values such as wk31 and wk311. In which case the second condition would evaluate to true for both and pick up an incorrect value:
regex = new RegExp("wk(/\d{" + bracket.toString().length + "})", "g");
if (reference.hasOwnProperty(i) && i.indexOf("wk" + bracket) !== -1 && regex.test(i)) {
Javascript
function findUpperPercentile(wk, number, reference){
var upperPercentile = "_100th";
var wkArray = reference['wk'+wk];
for (var i in wkArray ){
if (wkArray[i]>number){
upperPercentile=i
}
}
return upperPercentile;
}

Querying a stylized list with dynatable

Although I have been searching high and low to find the answer to this question, I have not been able to find it. Should there be a well-hidden corner of the internet that I have not searched that does contain the answer to this question, please let me know.
Anyway, on the Dynatable website there is an example to query a table for a certain value. If your input html is indeed a table, this seems to work, but if you're using a stylized listthis produces the following error in my case:
Uncaught TypeError: Cannot read property 'length' of null
Which traces back to line 1582 of the dynatable.jquery.js file:
// Find an object in an array of objects by attributes.
// E.g. find object with {id: 'hi', name: 'there'} in an array of objects
findObjectInArray: function(array, objectAttr) {
var _this = this,
foundObject;
for (var i = 0, len = array.length; i < len; i++) {
var item = array[i];
// For each object in array, test to make sure all attributes in objectAttr match
if (_this.allMatch(item, objectAttr, function(item, key, value) { return item[key] == value; })) {
foundObject = item;
break;
}
}
The following it my select element:
<select id="filter-prop" name="prop">
<option>All</option>
<option>First Run</option>
<option>Rejected</option>
</select>
And the dynatable conversion of my list:
// Function that renders the list items from our records
function ulWriter(rowIndex, record, columns, cellWriter) {
var cssClass = record.prop, li;
if (rowIndex % 3 === 0) { cssClass += ' first'; }
li = '<li class="' + cssClass + '"><div class="thumbnail"><div class="thumbnail-image">' + record.thumbnail + '</div><div class="caption">' + record.caption + '</div></div></li>';
return li;
}
// Function that creates our records from the DOM when the page is loaded
function ulReader(index, li, record) {
var $li = $(li),
$caption = $li.find('.caption');
record.thumbnail = $li.find('.thumbnail-image').html();
record.caption = $caption.html();
record.label = $caption.find('h3').text();
record.description = $caption.find('p').text();
record.color = $li.data('color');
record.prop = $li.attr('class');
}
var pictable = $('#picturelist').dynatable({
table: {
bodyRowSelector: 'li'
},
features :{
recordCount: false,
sorting: false,
},
dataset: {
perPageDefault: 10,
perPageOptions: [5, 10, 15, 20]
},
writers: {
_rowWriter: ulWriter
},
readers: {
_rowReader: ulReader
},
params: {
records: 'objects'
}
}).data('dynatable');
$('#filter-prop').change( function() {
var value = $(this).val();
if (value === "All") {
pictable.queries.remove("Prop");
} else if (value === "First Run") {
pictable.queries.add("Prop","span4 firstrun rejected");
pictable.queries.add("Prop","span4 firstrun");
} else if (value === "Rejected") {
pictable.queries.add("Prop","span4 firstrun rejected");
pictable.queries.add("Prop","span4 rejected");
};
pictable.process();
});
I have not changed much from the examples of the website. The most I did was merge the list example with the query example. Again, if I apply a similar method to a table, it seems to work, but for my list it doesn't. What is going wrong?
The docs weren't very clear here, but I solved the same problem for myself earlier today. Here is your code in working order:
var pictable = $('#picturelist')
.bind('dynatable:init', function(e, dynatable) {
dynatable.queries.functions['prop'] = function(record, queryValue) {
if ( record.prop == queryValue )
{
return true;
}
else
{
return false;
}
};
})
.dynatable({
table: {
bodyRowSelector: 'li'
},
features :{
recordCount: false,
sorting: false
},
dataset: {
perPageDefault: 10,
perPageOptions: [5, 10, 15, 20]
},
writers: {
_rowWriter: ulWriter
},
readers: {
_rowReader: ulReader
},
params: {
records: 'objects'
}
}).data('dynatable');
$('#filter-prop').change( function() {
var value = $(this).val();
if (value === "All")
{
pictable.queries.remove("prop");
}
else
{
pictable.queries.add("prop", value)
}
pictable.process();
});
Cheers

Categories