Add objects to array javascript, and associative array? - javascript

I'd like to create array filters_array, first thing I noticed in console is that filter_group is nowhere to be found, is this a correct way to save objects?
Second, on second click I want array to grow, but at this point it is only overwritten, what am I doing wrong?
//
var filters_array;
//Ajax call to filter movies, grab them and reload container
$(".option-set a").on("click", function(){
var filter_value = $(this).data("filter-value");
var filter_group = $(this).parents("ul").data("filter-group");
filters_array = {filter_group : filter_value};
console.dir(filters_array);
$.ajax({
url: templatePath + "getmovies.php",
type: "GET",
data: "",
cache: false,
success: function (data){
console.dir("ajax call success!");
}
});
return false;
});

"Associative arrays" in JavaScript are simply objects. We usually call them "objects" or "maps", to avoid confusing them with "arrays" (which aren't really arrays in JavaScript, but let's ignore that for now).
You want to initialize your filters_array with a blank object:
var filters_array = {};
...and then within the click handler, to add an entry to it with the key being the value of the filter_group variable and the value being the value in the filter_value variable:
filters_array[filter_group] = filter_value;
So for instance, if filter_group had the value "foo" and filter_value had the value "bar", you'd end up with a property on filters_array called foo with the value "bar". You could then access that property in several ways:
console.log(filters_array["foo"]); // "bar"
console.log(filters_array.foo); // "bar"
var x = "foo";
console.log(filters_array[x]); // "bar"
// Loop through all of the filter groups you've added
var key;
for (key in filters_array) {
// here, `key` will be `"foo"` (for instance)
console.log(filters_array[key]); // One of these will be "bar"
}

I'd like to create array filters_array, first thing I noticed in console is that filter_group is nowhere to be found, is this a correct way to save objects?
Yes, it is the right way, but it is right that you can't see it from the console, it is declared inside the function's scope. But you can do this if you need to access it from the outside:
var filters_array, filter_value, filter_group; //hoisted here
//Ajax call to filter movies, grab them and reload container
$(".option-set a").on("click", function(){
filter_value = $(this).data("filter-value");
filter_group = $(this).parents("ul").data("filter-group");
filters_array = {filter_group : filter_value};
console.dir(filters_array);
$.ajax({
url: templatePath + "getmovies.php",
type: "GET",
data: "",
cache: false,
success: function (data){
console.dir("ajax call success!");
}
});
return false;
});
Second, on second click I want array to grow, but at this point it is only overwritten, what am I doing wrong?
Well that's simple, you're initializing it again and again assigning it a new object every time, you have to do this:
filters_array[filter_group] = filter_value;
After having assigned to filters_array an empty object outside the function scope. Obviously you need to remove filters_array = {filter_group : filter_value}; and replace it with that line!

Related

Bypass a set parameter when calling a JavaScript method?

I know it has been asked and answered how to set a default parameter for a javascript function by Tilendor
I was wondering if I had a function containing a series of booleans.
For example, a function called 'anAnimal' and as a default I set a value of false to three propertys. fly, swim, and climb.
What would I do if I just want to pass in an argument of true to my property called climb?
Currently when calling in the method I have to pass in a value of false for fly and swim even though I have already predefined them as false.
This is what I am attempting and I would like the result to say true instead of false
function anAnimal (fly = false, swim = false, climb = false) {
this.canFly = fly;
this.canSwim = swim;
this.canClimb = climb;
}
var cat = new anAnimal(true)
var theCat = 'This cat can climb: ' + cat.canClimb;
document.write(theCat);
You can pass an object instead of arguments and populate default option based on inputs.
function anAnimal(obj) {
var defaults = {
fly: false,
swim: false,
climb: false
}
//copy the values of all enumerable own properties from one or more source objects to a target object.
Object.assign(defaults, obj);
//Assign the values
this.canFly = defaults.fly;
this.canSwim = defaults.swim;
this.canClimb = defaults.climb;
}
var cat = new anAnimal({
climb: true
});
var theCat = 'This cat can climb: ' + cat.canClimb;
document.write(theCat);
However I would recommend to use setters i.e. setClimb()

Storing Jquery reference

Is it possible to store the reference to an element in an array or object without having a unique ID on the element?
I am having trouble with storing a subtable in another table so I can reference it later. I get the table by class with this code:
$(this).parent('tr').parent().find('.tableSomeTable');
Is the only solution to have unique id's on each element and use the .selector method?
More of my code. Abit simplified.
var rows = [];
var historyLoad;
$(document).on("click", '.details-control', function (e) {
var t = $(this);
var tr = t.closest('tr');
var row = t.parent().parent().parent().DataTable().row(tr);
var id = t.closest('tr').attr('id');
var object = {
id: id,
btnHistory: t.parent('tr').next().find('#btnHistory'),
tblHistory: t.parent('tr').parent().find('.tableHistory'),
historyLoad: historyLoad
};
if ($.inArray(id, rows) > -1) {
loadData = false;
}
else {
loadData = true;
loadHistory(object);
rows.push(object);
}
};
Here is where I am having trouble retrieving the correct elements. And I also want to save the ajaxHistory element to my object (which is working fine).
This code is not working, but if I change it to $(result.btnHistory.btnHistory.selector) I get the object. But this doesn't seem to work very good with multiple rows.
function loadHistory(result) {
result.ajaxHistory = $.ajax({
...
beforeSend: function () {
$(result.btnHistory).html(<loading txt>);
$(result.tblHistory).find('tbody').html(<loading txt>);
},
....
success: function (data) {
if (data.TotalRecordCount > 0) {
$(result.tblHistory).find('tbody').html('');
$.each(data.Records, function (e, o) {
$(result.tblHistory).find('tbody').append(<data>)
});
}
else {
$(result.tblHistory).find('tbody').html(<txt no records>);
}
$(result.btnHistory).html(<txt loading done>));
},
First off, if you are trying to find the parent table, try
var $myObj = $(this).closest('table.tableSomeTable');
instead of navigating parents.
As far as storing the jQuery reference, define a variable and then store it. The above will store the object in $myObj but that is locally scoped. If you need a global variable then define it globally and just assign it here. If you want to define it as a property within an object then define it that way. It really comes down to a scope question at this point.
EDIT: Just saw your added content.
First off, don't name it 'object'. This may run into key word issues. Use var myObj or similar instead. Next, object.btnHistory is a reference to a jQuery object. So, when you pass it to loadHistory, you do not need to apply the $(...) again. Just use the reference directly: result.btnHistory.html(...). A good habit to get into is prepending you jQuery variables with $ so you remember it is already a jQuery variable.
The .find() method returns a jQuery object. So the answer is, yes, you can store this return object in a variable:
var $yourObject = $(this).parent('tr').parent().find('.tableSomeTable');

Ember.js how to remove object from array controller without ember data

I am trying to update the arraycontroller model after deleting a record using jquery ajax.I can add a new object using self.pushObject(data), but i cannot remove the object using self.removeObject(data). can someone please help. ("data" is the object that i removed, the server sends it back after removing it in server.)
removeTodo: function(id) {
var page_id = id;
self = this;
Ember.$.ajax({
url: url+id,
type: "DELETE"
}).then(function(data) {
self.removeObject(data);
});
}
data might have the same properties, but it isn't the object that exists in your array. See here, both of these objects look exactly alike, but they are different objects, and as such aren't equal.
{ foo : 7 } != { foo : 7 }
When removing from a collection, if you pass in the object to be removed, that object must exist in the collection.
You would want to first find the object, then remove it from the collection.
.then(function(data) {
var obj = self.findBy('id', id); // assuming the object has a property 'id'
self.removeObject(obj);
});

How to automatically assign value to another key depending on some other key's value in an Object

How do you achieve the following thing in Javascript
1) var MyObject={
2) tableView:true,
3) chartView:!(this.tableView)
4) }
The code at line number 3 is not working. Whats wrong in that line ?
What i basically want to do is set "chartView" to opposite of "tableView" whenever tableView is set from code.
Since you're in the process of creating the object, this is not bound to that object. Moreover, since you want chartView to always evaluate to the opposite of tableView, even if the latter changes further down the line, a function would be a better approach:
var MyObject = {
tableView: true,
chartView: function() {
return !this.tableView;
}
};
Now you can do:
var chartView = MyObject.chartView(); // false.
MyObject.tableView = false;
chartView = MyObject.chartView(); // true.
You can't use this to refer to an object in an object literal's properties. You can use this inside a function that is a method of that object:
var MyObject = {
tableView: true,
chartView: function () {
return !this.tableView;
}
}
Based on your requirement, this may be an answer too,
var MyObject = {
view : function(bool){
this.tableView = bool;
this.chartView = !(bool);
}
tableView: true,
chartView: false
}
MyObject.view(false)
console.log(MyObject.tableView); // Outputs false
console.log(MyObject.chartView) // Outputs true
This way you will always have opposite of tableView in chartView with a single function call.

jquery variable scope problem

I have a chat class with two methods: updateChat and sendChat.
//chat.js
var state;
var room;
function Chat (theRoom) {
this.update = updateChat;
this.send = sendChat;
this.room = theRoom;
}
function updateChat(){
alert('ROOM: '+this.room);
$.ajax({
type: "POST",
url: "/chat/process.php",
data: {
'function': 'update',
'state': state,
'room': this.room
},
dataType: "json",
success: function(data){
if(data.text){
for (var i = 0; i < data.text.length; i++) {
$('#chat-area').append($("<p>"+ data.text[i] +"</p>"));
}
}
if(data.state)
state = data.state;
}
});
}
}
//send the message
function sendChat(message, nickname)
{
alert('A'+state); //20
//XXX
updateChat();
alert('B'+state); //20
$.ajax({
type: "POST",
url: "/live-event/chat/process.php",
data: {
'function': 'send',
'message': message,
'nickname': nickname,
'room': this.room
},
dataType: "json",
success: function(data){
alert('C'+state); //wrong!: 2 //it should be 20!
//XXX
updateChat();
alert('D'+state); //21
},
});
}
The constructor of the chat object:
var chat = new Chat(4); //4 = the number of the chat room
chat.send('test', 'tester');
My problem are the method calls at the locations marked with XXX.
In the updateChat() method, this.room is undefined if I call the updateChat methods like that.
But I need to pass the room number to get the right state (state is simply the number of lines in the chat room's text file).
I think it's a problem with variable scope or with the methods not being called in the context of the object.
You need to maintain this when calling those methods, so instead of this:
updateChat();
You can use .call() to maintain context (so this doesn't revert to window inside the called function), like this:
updateChat.call(this);
Or call the method on the object as #casablanca points out below:
this.update();
There also one more issue, this won't be what you want in your $.ajax() callbacks, it'll be the ajax settings object by default, so you need to set the context option to maintain it, like this:
$.ajax({
context: this,
type: "POST",
//...rest of your current options/methods
You may find this easier to grasp if you forget about classes. What you've written there is not a class. There are no classes in JavaScript. You've written a constructor function, but it's of somewhat dubious value because you're assigning the members individually for every instance. The main purpose of constructor functions is to take advantage of prototype-inheritance, so you'd assign the "methods" to the constructor function's prototype.
function Chat (theRoom) {
this.room = theRoom;
}
Chat.prototype.send = sendChat;
Chat.prototype.update = updateChat;
That way, each object created with new Chat(r) will only need to store the room number, and will not need to store the two methods as properties.
Alternatively, just write a createChatRoom function:
var createChatRoom = function(room) {
return {
update: function() {
alert('updating: ' + room);
// ... other stuff
},
sending: function() {
alert('sending: ' + room);
// ... other stuff
}
};
};
The beauty of that is probably obvious: you don't need to prefix anything with this. The room parameter is in scope to the method definitions, and is also truly private (cannot be modified except through calls to the methods. And the caller doesn't have to remember to put new. They just call the function and get back a fresh object with two methods in it.
You can even safely do this:
setTimeout(chatRoom.update, 10);
The update function "knows" what object it is associated with. It never needs to be told which this to use.
This is so convenient and useful, unless I'm expecting to create very large quantities of objects, I don't bother with constructor functions, new, prototype, etc.

Categories

Resources