JavaScript: Why isn't my closure working? - javascript

The following code is only assigning the value of the last .enter_form input to the last MYAPP.list[0].responses[MYAPP.score.round].form[key] (where key is the only thing that varies). I think it's because only the last value of the key is being passed to addEntry(), but I can't figure out how to get around that.
$('.enter_form input').each(function() {
var key = $(this).attr('id');
var val = $(this).val();
userDict[key] = val;
MYAPP.list[0].responses[MYAPP.score.round].form = [];
function addEntry() {
return function(k) {
MYAPP.list[0].responses[MYAPP.score.round].form[k] = {'entry': userDict[k]};
}(key);
}
addEntry();
}

Your addEntry function is redundant since each iteration is already run inside it´s own scope so key and val are preserved properly (hope that explanation makes sense). Also the array you where inserting into was overwritten each iteration as well, so at the end of the .each() you end up with an array with only 1 value. It should also be an object rather then an array, even if the id's are numerical.
// you where overwriting this each iteration
MYAPP.list[0].responses[MYAPP.score.round].form = {};
$('.enter_form input').each(function() {
var el= $(this); // cache instead of creating a new jQuery object each time
var key = el.attr('id');
var val = el.val();
userDict[key] = val;
MYAPP.list[0].responses[MYAPP.score.round].form[key] = {'entry': userDict[key]};
}); // ); was also missing
Should work.

It's a bit hard to work out what it's meant to do, but I think this is probably it:
MYAPP.list[0].responses[MYAPP.score.round].form = [];
$('.enter_form input').each(function() {
var $this = $(this),
key = this.id,
val = $this.val();
userDict[key] = val;
MYAPP.list[0].responses[MYAPP.score.round].form[key] = {
'entry': val
};
});
That's based on your saying that "...key is the only thing that varies" (presumably $(this).val() also varies, but I took your point). It will add entries to MYAPP.list[0].responses[MYAPP.score.round].form for each of the form's input ids, as well as adding them to the userDict map.
As a side note, if the id values on the input elements aren't purely numeric, then I suspect you want to start with a blank object:
MYAPP.list[0].responses[MYAPP.score.round].form = {};
// ^^-- change is here
...rather than an empty array:
MYAPP.list[0].responses[MYAPP.score.round].form = [];
...although since arrays are objects, it works even if you're adding non-numeric properties.
Off-topic: No need for $(this).attr('id'). Just use this.id.

Related

Determine if value exists in JavaScript "hash table"

I have built a JavaScript object that functions as a hash table.
var hashTable = {};
The table consists of key value pairs that are manually built. The table will be used to generate a new value based on an old value, or key, in the table.
//hashTable['old_value'] = new_value;
hashTable['115004568543'] = 115004567503;
hashTable['115004545983'] = 360000857366;
hashTable['115004723526'] = 360000865566;
hashTable['115004723646'] = 360000865566;
I have another variable that is compared to the keys in the hash table. If it matches a key in the hash table, then it can be used to capture the new value mapped to it.
For example, let's say some_value is declared.
some_value = '115004568543';
Since it matches a key value (or old_value) in the hash table, I can get the new value by calling
var new_value = hashTable[some_value];
// new_value is going to be equal to 115004567503 due to the mapping above
My problem is that I have two different hash tables that "some_value" is being compared against. I want to see if the first value in the hash is present either in the first hash table OR in the second hash table. So I have been working with:
var hashTable = {};
hashTable['115004568543'] = 115004567503;
hashTable['115004545983'] = 360000857366;
var hashTable2 = {};
hashTable2['115004702483'] = 360000857366;
hashTable2['115004560766'] = 360000857366;
var some_value = '115004545983';
if (hashTable.includes(some_value)) {
var new_value = hashTable[some_value];
//Do some other stuff with new_value
}
else if (hashTableTwo.includes(some_value)) {
var new_value = hashTableTwo[some_value];
//Do some other stuff with new_value
}
Additionally, some_value will exist in the first hash table, the second hash table, or not at all. It will not exist multiple times.
MY QUESTION: I am trying to use hashTable.includes() to see if some_value is present in either of the two hash tables. It isn't working. What is the best way to determine if some_value is a value in one of the hash tables?
When I try to call hashTable.includes(some_value) I get
Uncaught TypeError: hashTable.includes is not a function
Array.includes() is an array method. Since your hashtable is based on an object, it doesn't support this method.
If your values aren't falsy (false, undefined, null, 0, NaN) you can use logical short-circuit evaluation to assign the value:
var new_value = hashTable[some_value] || hashTableTwo[some_value] || some_value;
If they might be falsy, you can use the in operator to check if they exist in the object:
if (some_value in hashTable) {
var new_value = hashTable[some_value];
} else if (some_value in hashTableTwo) {
var new_value = hashTableTwo[some_value];
//Do some other stuff
}

TypeError: 'undefined' is not an object in Javascript

I have a piece of Javascript code that assigns string of values to a string array.
Unfortunately if I try to add more than one string to the array, my UI simulator(which runs on JS code) closes unexpectedly. I have tried debugging but I cannot find anything. I am attaching that piece of code where the issue is. may be you guys could find some flaw? On the pop up button click the values I selcted on the UI should get stored in the array and I have a corressponding variable on the server side to handle this string array.
_popupButtonClick: function (button) {
var solutions = this._stateModel.get('solutionName');
var i;
var solutionsLength = solutions.length;
var selectedSolution = [solutionsLength];
this.clearPopupTimer();
if (button.position === StatusViewModel.ResponseType.Ok) {
for(i=0;i<solutionsLength;i++)
{
if(this._list.listItems[i].selected)
{
selectedSolution[i] = this._list.listItems[i].options.value;
}
}
this._stateModel.save({
selectedsolutions: selectedSolution,
viewResponse: StatusViewModel.ResponseType.Ok
});
} else {
this._stateModel.save({
viewResponse: StatusViewModel.ResponseType.Cancel
});
}
}
Change
var selectedSolution = [solutionsLength];
to
var selectedSolution = [];
This makes your array have an extra item that might be causing a crash.
Also,
you have an
if(this._list.listItems[i].selected)
{
selectedSolution[i] = this._list.listItems[i].options.value;
}
But no corresponding else, so your array has undefined values for i which are not entering the if.
Maybe adding an empty string might solve it:
if(this._list.listItems[i].selected)
{
selectedSolution[i] = this._list.listItems[i].options.value;
}
else
{
selectedSolution[i] = "";
}
The code is looking fine but there seems to be a piece of code which can cause error. For example, you are assigning var selectedSolution = [solutionsLength]; and for example solutionsLength is 5 then your loop runs for 5 times
for(i=0;i<solutionsLength;i++) // runs for 5 times
{
if(this._list.listItems[i].selected)
{
// but selectedSolution = [5]; which is on 0th index and from 1st to 4th index it is undefined
selectedSolution[i] = this._list.listItems[i].options.value;
}
}
So you can try to use push() like
selectedSolution.push(this._list.listItems[i].options.value);
and on initialization change it like,
var selectedSolution = [];
Hopefully this will solve your problem.
var selectedSolution = [solutionsLength];
keeps the value in the selectedSolution variable.
var selectedSolution = [3];
selectedSolution[0] gives the values as 3
So make it simple
var selectedSolution = [];

remove items from array with the same id one by one

the problem is that I have multiple objects with the same id. As you can see this works when it comes to removing all the items with the same id. How I can remove the objects one by one no matter if they are the same ID...thanks
individualObjects:[],
actions:{
increment:function(){
var obj = this.get('object');
this.get('individualObjects').pushObject(obj);
},
decrement:function(){
var obj = this.get('object');
var filter = this.get('individualObjects').findBy('obj_id', obj.get('obj_id'));
this.get('individualObjects').removeObject(filter);
}
}
Well to filter array you would need to use Array.filter to find out the items that do not belong in the "individualObjects" and later simply remove them by using "removeObjects"
decrement:function(){
var objects = this.get('individualObjects')
var notWanted = objects.filterBy('obj_id', this.get('object.obj_id'));
this.get('individualObjects').removeObjects(notWanted);
}
and solution 2
decrement:function(){
var removeObj = this.get('object');
var objects = this.get('individualObjects')
// As the condition is true given object is returned
var notWanted = objects.filter(obj => { return obj.get('obj_id') === removeObj.get('obj_id')  });
this.get('individualObjects').removeObjects(notWanted);
}
Ok so you want to remove items one by one. Weird but can be accomplished
first get the length for
var notWantedCount = objects.filterBy('obj_id', this.get('object.obj_id')).length;
Now
for(var i=0; i <= notWantedCount; i++) {
var toRemove = individualObjects.findBy('obj_id', obj.get('obj_id'));
individualObjects.removeObject(toRemove);
// Make some custom actions one by one.
}
I don't know ember, but you'll want to do a foreach on the array, and then test for id on each one. It should be something like this:
decrement:function(){
var obj = this.get('object');
self = this;
this.get('individualObjects').each(function(individualObject) {
if (individualObject.get('obj_id') == obj.get('obj_id'))
... you want to do something here? ...
self.get('individualObjects').removeObject(individualObject);
}
}
That way you can remove each object individually. Running any necessary code before or after it's removed. If you want to sort it first, you can do that before running the each function.

Assign value of variable from JS array based on key

I have a variable that takes its value from the current object's ID attribute, it will always look something like filtercolor-red:
$('.facet-options-list li input[id*=filtercolor]').each(function() {
var filterColor = $(this).attr('id');
...
});
I also have an array that lists possible ID's and a corresponding HEX code:
var activeFilterBg;
var filterBgColor = [];
filterBgColor = {
filtercolor-black: '#171710',
filtercolor-blue: '#4C94B6',
filtercolor-brown: '#50443D',
filtercolor-gold: '#F6D069',
filtercolor-green: '#96B14D',
filtercolor-grey: '#A8AAA5',
filtercolor-orange: '#DB5E46',
filtercolor-pink: '#E78EB1',
filtercolor-purple: '#59547E',
filtercolor-red: '#D22200',
filtercolor-silver: '#EBEBEB',
filtercolor-white: '#FFF'
};
What I'd like to do is take filterColor and assign activeFilterBg the appropriate HEX code from filterBgColor. I could do this with a switch, but that seems kind of sloppy and gives a lot of room for mistakes in the future.
Do I have an option to somehow lookup the correct key and then assign a variable based upon it?
That's not an array, that's an object. You assign an array to the variable, but then you immediately replace that with an object. An object works well for this, so just skip that array. (Note though, as Jordan pointed out, that the parameter names has to be quoted when they contain dashes.)
You can use the bracket syntax to access the object properties using the variable:
var activeFilterBg;
var filterBgColor = {
'filtercolor-black': '#171710',
'filtercolor-blue': '#4C94B6',
'filtercolor-brown': '#50443D',
'filtercolor-gold': '#F6D069',
'filtercolor-green': '#96B14D',
'filtercolor-grey': '#A8AAA5',
'filtercolor-orange': '#DB5E46',
'filtercolor-pink': '#E78EB1',
'filtercolor-purple': '#59547E',
'filtercolor-red': '#D22200',
'filtercolor-silver': '#EBEBEB',
'filtercolor-white': '#FFF'
};
$('.facet-options-list li input[id*=filtercolor]').each(function() {
var filterColor = $(this).attr('id');
activeFilterBg = filterBgColor[filterColor];
});
Check the object first with hasOwnProperty - and if the property exists, use it!
$('.facet-options-list li input[id*=filtercolor]').each(function() {
var filterColor = this.id; //$(this).attr('id');
var color;
if (filterBgColor.hasOwnProperty(filterColor) {
color = filterBgColor[filterColor];
} else {
color = "#FFF"; //not found
}
});
mapping the id to the color should be as simple as
var filterColor = $(this).attr('id');
var hexCode = filterBgColor[filterColor];
//then do whatever with the hexCode

Why this json swap code does not work?

I have this fun :
swapjson = function (j1,j2)
{ var jj = JSON.parse(JSON.stringify(j1));
j1 = JSON.parse(JSON.stringify(j2));
j2 = jj;
}
I have also:
var myjson1 = {'x':1000, 'y':1000};
var myjson2 = {'x':2000, 'y':-2000};
swapjson (myjson1,myjson2);
console.log myjson1.x
1000 ?????
And I discover that inside the swapjson function the swap is made but not after call.
What is happen ? I dont understand what I'm doing bad...
Any help would be appreciated.
You can't replace the entire object like that, as the object itself isn't passed by referenced.
You can however change properties of the object passed, and it will stick, as a copy of the object is passed in.
So instead of parsing to strings and back to objects you can just iterate over the two objects keys, and replace one by one
swapjson = function (j1, j2) {
var temp = {};
for (key in j1) {
temp[key] = j1[key];
delete(j1[key]);
}
for (key in j2) {
j1[key] = j2[key];
delete(j2[key]);
}
for (key in temp) {
j2[key] = temp[key];
}
}
FIDDLE
You copy the value of myjson1 (which is a reference to an object and nothing to do with JSON) into j1, and the value of myjson2 into j2.
Then you overwrite the value of j1 and the value of j2.
You never change the values of myjson1 or myjson2.

Categories

Resources