BackboneJS: iterate on model attribute and change value - javascript

I want to make a function with functionality like toJSON()'s functionality which returns and edits model.
My question is how to iterate on model's attribute and edit the specific value of the attribute you selected.
If have a model e.g:
Item = Backbone.Model.extend({
defaults: {
name: '',
amount: 0.00
},
toHTML: function(){
// i think this is the place where
// where i can do that function?
//
console.log(this.attribute)
}
});
var item = new Item;
item.set({name: 'Pencil', amount: 5}):
item.toJSON();
-> {name: 'Pencil', amount: 5}
// this is the function
item.toHTML();
-> {name: 'Pencil', amount: 5.00}

You can iterate over an object using a for ... in loop and then use toFixed to format the number:
toHTML: function() {
var attrs = { }, k;
for(k in this.attributes) {
attrs[k] = this.attributes[k];
if(k === 'amount')
attrs[k] = attrs[k].toFixed(2);
}
return attrs;
}
Note that amount will come out as a string but that's the only way to get 5.00 rather than 5 to come out. I'd probably leave the formatting up to the template and not bother with this toHTML implementation.
Demo: http://jsfiddle.net/ambiguous/ELTe5/

If you want to iterate over a model's attributes, use the attributes hash:
// Inside your model's method
for(attr in this.attributes){
console.log(attr, this.attributes[attr]);
}
Here's a jsFiddle using your example code.

Though the answers provided here are correct and would do what you want. But I think the better way would be to use the underscore functions for this purpose.
for simple looping you can use
_.each(list, iteratee, [context])
_.each(model.attributes, function(item, index, items){
console.log(item);
console.log(index);
})
you can also use specialized functions as per your specific need. Like if you are want to have a new result array as a result of applying some function on every element of your list, map can be the best option for you.
_.map(list, iteratee, [context])
var newList = _.map(model.attributes, function(item, index, list){
return item * 5;
})
I would recommend you to go through the documentation of underscore and backbone for the best function for your need.

Related

Remove a record in a Object Array jQuery

EDIT : Included more details
Hi I have a Object Array in jQuery which looks like this,
My question is how can I delete a record from that object array by columnheader as parameter. I know there is this
var result = $.grep(records, function(e){ return e.columnheader == currentheader; });
but grep i only used to check if there's a matching data based on currentheader that i passed in. What if I want to delete?
I want to delete a record on the fly as I am looping in that object array, lets I have. data contains all object arrays that is shown in the image.
$.each(data, function(key,value) {
// Let's say I want the code here to delete a record in the current object array that I'm looping into.
});
Thanks
You can use filter()
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
arr = arr.filter(function(e) {
return e.columnheader !== currentheader;
});
Demo
var arr = [{
name: 'John Skeet',
rank: 1
}, {
name: 'T.J.Crowder',
rank: 10
}];
console.log(arr);
arr = arr.filter(function(e) {
return e.rank !== 10
});
console.log(arr);
UPDATE
I want the code here to delete a record in the current object array that I'm looping into
Changing a property from object in array.
var arr = [{
name: 'John Skeet',
rank: 1
}, {
name: 'T.J.Crowder',
rank: 10
}];
$.each(arr, function(index, obj) {
if (obj.rank === 10) {
arr[index].rank = 9;
}
});
console.log(arr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
You can use the JavaScript splice method to do it. First find the index of your object in the array then use the method like that :
your_array.splice(obj_index,0);
EDIT
The easy way but not optimized is to use a for loop to get the index, a better solution is to use linq.js to get the object, then your_array.indexOf(your_obj);
EDIT 2
You can download linq.js here Linq.js
You can use it like this:
function DelteObjFromArray(your_value){
var objToDelete = Enumerable.From(your_array).Where(function (x) { return x.your_property == your_value; }).FirstOrDefault();
var objIndex = your_array.indexOf(objToDelete);
your_array.splice(objIndex,1);
}

Javascript array object arrays

THis is going to sound like a stupid question but here it goes. I have a js array formatted like so
var locationID = [
{ ID: "ID1", location: "location1" },
{ ID: "ID2", location: "location2" },
{ ID: "ID3", location: "location3" },
];
I am trying to loop through the array
for(i = 0; i < locationID.length;i++){
var object = locationID[i];
}
I want to get both elements from the inner array so the ID and location. would I do this by object[0] or object["ID"] for example.
Also is there a more efficient way to do what I need to do like a for each loop or something along those lines.
Use object.ID or object['ID'].
Objects {} in JavaScript are associative, or named arrays. (Also known as a map in many languages. They are indexed by strings (in this case).
Arrays [], are indexed by integral numbers, starting from 0 and counting up to n-1, where n is the length of the array.
If you want to programmatically go through all the (key, value) pairs in each object, you can use this method.
Quotations (String Literals)
To reiterate my comment below about single and double quotes:
If you're talking about inside the [], no [,they're not important]. JavaScript treats single
quotes and double quotes pretty much the same. Both of them denote
string literals. Interestingly, you can use single quotes inside
double quotes or vice-versa: "I wanted to say 'Hello world!'" would be
a (single) valid string, but so would 'But I accidentally said "Goodbye".
This is an optimized loop based from the book of Nicholas Zackas (YAHOO performance chief). I am performing a cached array length to prevent re-evaluation of array length on every iteration of the loop. Please check jsperf.com. Also, native loop is always faster than method based loops jQuery.each and Array.prototype.forEach. This is also supported on browsers below ie8
var currentItem,
locationInfo = [
{ ID: "ID1", location: "location1" },
{ ID: "ID2", location: "location2" },
{ ID: "ID3", location: "location3" },
];
for (var i = 0, len = locationInfo.length; i < len; i++) {
currentItem = locationInfo[i];
console.log(currentItem.ID);//I prefer this because it shrinks down the size of the js file
console.log(currentItem["ID"]);
}
what you have already will return each of the objects in the JSON as you run the loop. What you need is something like
for(i = 0; i < locationID.length;i++){
var object = {locationID[i].ID, locationID[i].location};
}
Remember properties of objects are accessed by their keys since they are key-value pairs.
For loops are going to be your best bet as far as speed, here's how you'd do it with forEach (IE 9+)
locationID.forEach(function(location, i){
console.log(location['ID'])
console.log(location['location'])
});
jQuery make's it a little easier but runs slower
$.each(array, function(i, item){
});
http://jsperf.com/for-vs-foreach/75
Also here a useful link: For-each over an array in JavaScript?
You can use the forEach method, which make your code more cleaner.
See forEach
locationID.forEach(function(elm){
//Here, elm is my current object
var data = elm;
console.log(data.ID):
console.log(data.location);
});
EDIT :
Then for your second question, you should filter and map methods.
function findNamebyID(id){
//Filter by id and map the data to location
return locationID.filter(function(elm){
return elm.ID === id;
}).map(function(elm){
return elm.location;
})
}
Something as:
var location = locationID.reduce(function(ob, cur) {
ob[cur.ID] = cur.location;
return ob;
}, {});
The result you get is:
Object {ID1: "location1", ID2: "location2", ID3: "location3"}
Meaning you can do:
location.ID1 // location1
location.ID2 // location2
...
an alternative to your loop, would be to use the JavaScript for (.. in ..) since you aren't really using the iterator; it just adds fluff
for(i = 0; i < locationID.length;i++){
var object = locationID[i];
}
could be written as:
for (item in locationID) {
var object = item;
}

How would you count the instances of objects in arrays within an array

So, essentially I am getting a set of records as an array of objects like
[{name: tyler, categories: ["friends", "neighbor"]}, {name: joe, categories: ["friends"]}].
and I want to count the contents of the internal array instances. So in this example, the return would be friends: 2 and neighbor: 1. As some background info, I am getting a collection of records from mongo within the meteor framework. I am then using fetch() to convert these records to an array of objects like above. I then want to use these objects to create a pie graph based on the counts of the specific instances of each object within the inner array of each object (these objects would be the ones returned by the db query) within the outer array.
You can write a simple function to count your categories counts and store the result in a dictionary of key/value pairs.
function countCategories(docs){
// accumulate results inside a JS object acting as a key/value dict
var result = {};
docs.forEach(function(doc){
doc.categories.forEach(function(category){
// initialize count to 0 when a new key is found
if(_.isUndefined(result[category])){
result[category] = 0;
}
// increment the corresponding count
result[category]++;
});
});
return result;
}
Given the sample data in your question, this function will return :
Object {friends: 2, neighbor: 1}
EDIT :
You can then convert this dictionary to an array of objects.
function convertToArray(dict){
var result = [];
_.each(dict, function(value, key){
var object = {
category: key,
count: value
};
result.push(object);
});
return result;
}
Using underscore and reduce:
result = _.reduce( data, function( counter, o ) {
_.each( o.categories, function(c){
counter[c] = 1 + _.result(counter, c, 0);
});
return counter;
}, {});
Demo in this fiddle
reduce goes through your array (first arg) and applies
the function you give it (second arg) and a starting value for
the memo (third arg). This memo is passed to each call to
your function as the first argument, you can us it to store
stuff you want to remember.
I've set the starting value for the memo to be an empty object
which we will use as a counter.
result = _.reduce( data, function( counter, o ) {
// current element of the array: o
// stuff you want to remember for: counter
return counter;
}, {});
You might attach a function to the array and count the elements inside of it.
yourArray = [1,2,3];
yourArray.countElements = function(){
var elements=0;
for(x=0;this[x]!=undefined;x++){
instances++
}
return instances;
};
yourArray.countElements(); // outputs 3
Modify this, using "neighbors" and "friends" instead of "elements" and counting them only if this["categories"]["the_category"] is different of undefined.
Also you could attach it to Array.prototype

Most efficient and clean way to push a value to an array only if it does not exist yet

Suppose an array named myArray containing several values but no duplicates.
Suppose I want to push a value into it only if it won't lead to duplicates presence.
How I determinate duplicates => by comparing value's id.
I thought about Lodash#uniq to do the trick:
myArray.push(aNewValue);
myArray = _.uniq(myArray,function(item){
return item.id;
});
However, I don't like the reassignment to the array and especially the fact that I have to push before checking...
Is there a more "functional" way to achieve it while being very short?
I don't want to iterate through the array explicitly in order to apply the check.
That's why I attempted to use Lodash.
You can check the presence of an item before adding it :
if(myArray.indexOf(aNewValue) == -1) {
myArray.push(aNewValue);
}
The most efficient way to do this is generally to use an object for uniqueness, because an object can have at most one key of a certain value. However, this is restricted to strings and things that stringify, since only strings can be object keys.
There are two approaches here. If you are using your array often, then you should keep parallel structures - an object for uniqueness check, an array for arrayness of it.
If you don't need your array often, i.e. you want to push a bunch of things and then have an array be unique, you can just use the object, and transform it into an array when you need it (which is somewhat expensive, so you only want to do it once, but still cheaper than manipulating two different structures all the time).
The first approach is illustrated here:
function Set() {
this.presence = {};
this.array = [];
};
Set.prototype.push = function(key, value) {
if (this.presence[key]) return;
this.presence[key] = true;
this.array.push(value);
};
var a = new Set();
a.push(3, { id: 3, value: "SOMETHING" });
a.push(7, { id: 7, value: "SOMETHING ELSE" });
a.push(3, { id: 3, value: "SOMETHING" });
console.log(a.array); // => only 2 elements
The second, here:
function Set() {
this.store = {};
};
Set.prototype.push = function(key, value) {
this.store[key] = value;
};
Set.prototype.array = function() {
var that = this;
return Object.keys(this.store).map(function(key) { return that.store[key]; })
};
...
console.log(a.array()); // note the newly added parentheses :)
Both of these are still cheaper than looking for presence inside the array using indexOf, even more so when you do your own iterating, except very much maybe in case the array is very short.
You could use Array.prototype.some() to find out if the value is already part of the array, e.g.:
if( myArray.some(function (elem) { return elem.id == newValue.id }) )
myArray.push(newValue);
You can't really get away with not looping through the array, though.

jQuery.map - Practical uses for the function?

I am trying to get a better understanding of the jQuery.map function.
So in general terms .map takes a array and "maps" it to another array of items.
easy example:
$.map([0,1,2], function(n){
return n+4;
});
results in [4,5,6]
I think I understand what it does. I want to under why would someone need it. What is the practical use of this function? How are you using this in your code?
Mapping has two main purposes: grabbing properties from an array of items, and converting each item into something else.
Suppose you have an array of objects representing users:
var users = [
{ id: 1, name: "RedWolves" },
{ id: 2, name: "Ron DeVera" },
{ id: 3, name: "Jon Skeet" }
];
Mapping is a convenient way to grab a certain property from each item. For instance, you can convert it into an array of user IDs:
var userIds = $.map(users, function(u) { return u.id; });
As another example, say you have a collection of elements:
var ths = $('table tr th');
If you want to store the contents of those table headers for later use, you can get an array of their HTML contents:
var contents = $.map(ths, function(th) { return th.html(); });
$.map is all about converting items in a set.
As far as the DOM, I often use it to quickly pluck out values from my elements:
var usernames = $('#user-list li label').map(function() {
return this.innerHTML;
})
The above converts the <label> elements inside a list of users to just the text contained therein. Then I can do:
alert('The following users are still logged in: ' + usernames.join(', '));
Map is a high-order function, that enables you to apply certain function to a given sequence, generating a new resulting sequence containing the values of each original element with the value of the applied function.
I often use it to get a valid selector of all my jQuery UI panels for example:
var myPanels = $('a').map(function() {
return this.hash || null;
}).get().join(',');
That will return a comma separated string of the panels available in the current page like this:
"#home,#publish,#request,#contact"
And that is a valid selector that can be used:
$(myPanels);// do something with all the panels
Example:
$.map($.parseJSON(response), function(item) {
return { value: item.tagName, data: item.id };
})
Here server will be returning the "response" in JSON format, by using $.parseJSON it is converting JSON object to Javascript Object array.
By using $.map for each object value it will call the function(item) to display the result value: item.tagName, data: item.id
Here's one thing you could use it for.
$.map(["item1","item2","item3"], function(n){
var li = document.createElement ( 'li' );
li.innerHTML = n;
ul.appendChild ( li );
return li;
});
Recently I discovered an excellent example of .map in a practical setting.
Given the question of How to append options to a selectbox given this array (or another array):
selectValues = { "1": "test 1", "2": "test 2" };
this StackOverflow answer uses .map:
$("mySelect").append(
$.map(selectValues, function(v,k) {
return $("<option>").val(k).text(v);
})
);
Converting code values to code text would be a possible use. Such as when you have a select list and each indexed value has a corresponding code text.

Categories

Resources