I am pretty new to the 'game' and was wondering if it's possible to order newly added data (through a form and inputs) to the Firebase numerically so each new data entry gets the ID (number of the last added data +1).
To make it more clear, underneath you can find a screenshot of how data is currently being added right now. The datapoint 0-7 are existing (JSON imported data) and the ones with the randomly created ID belong to new entries. I would like to have the entries to comply to the numbering inside of my Firebase, because otherwise my D3 bar chart won't be visualised.
var firebaseData = new Firebase("https://assignment5.firebaseio.com");
function funct1(evt)
{
var gameName = $('#nameInput').val();
var medalCount = $('#medalsInput').val();
var bool = $('#boolInput').is(':checked');
firebaseData.push().set({games: gameName, medals: medalCount, summergames: bool});
evt.preventDefault();
}
var submit = document.getElementsByTagName('button')[0];
submit.onclick = funct1;
UPDATE:
function funct1(evt)
{
var gameName = $('#nameInput').val();
var medalCount = $('#medalsInput').val();
var bool = $('#boolInput').is(':checked');
for (var i = 0; i < 10; i++)
{
firebaseData.child('7' + i).set({games: gameName, medals: medalCount, summergames: bool}(i)); };
Problem:
There are two ways to generate ids for your document nodes.
Calling .push() on your reference will generate that unique id.
Calling .set() on your reference will allow you to use your own
id.
Right now you're using .push().set({}), so push will generate an new id and the set will simply set the data.
// These two methods are equivalent
listRef.push().set({user_id: 'wilma', text: 'Hello'});
listRef.push({user_id: 'wilma', text: 'Hello'});
Using .set() without .push() will allow you to control your own id.
Using .push():
When managing lists of data in Firebase, it's important to use unique generated IDs since the data is updating in real time. If integer ids are being used data can be easily overwritten.
Just because you have an unique id, doesn't mean you can't query through your data by your ids. You can loop through a parent reference and get all of the child references as well.
var listRef = new Firebase('https://YOUR-FIREBASE.firebaseio.com/items');
// constructor for item
function Item(id) {
this.id = id;
};
// add the items to firebase
for (var i = 0; i < 10; i++) {
listRef.push(new Item(i));
};
// This will generate the following structure
// - items
// - LGAJlkejagae
// - id: 0
// now we can loop through all of the items
listRef.once('value', function (snapshot) {
snapshot.forEach(function (childSnapshot) {
var name = childSnapshot.name();
var childData = childSnapshot.val();
console.log(name); // unique id
console.log(childData); // actual data
console.log(childData.id); // this is the id you're looking for
});
});
Within the childData variable you can access your data such as the id you want.
Using .set()
If you want to manage your own ids you can use set, but you need to change the child reference as you add items.
for (var i = 0; i < 10; i++) {
// Now this will create an item with the id number
// ex: https://YOUR-FIREBASE.firebaseio.com/items/1
listRef.child('/' + i).set(new Item(i));
};
// The above loop with create the following structure.
// - items
// - 0
// - id: 0
To get the data you can use the same method above to loop through all of the child items in the node.
So which one to use?
Use .push() when you don't want your data to be easily overwritten.
Use .set() when your id is really, really important to you and you don't care about your data being easily overwritten.
EDIT
The problem you're having is that you need to know the total amount of items in the list. This feature is not implemented in Firebase so you'll need to load the data and grab the number of items. I'd recommend doing this when the page loads and caching that count if you really desire to maintain that id structure. This will cause performance issues.
However, if you know what you need to index off of, or don't care to overwrite your index I wouldn't load the data from firebase.
In your case your code would look something like this:
// this variable will store all your data, try to not put it in global scope
var firebaseData = new Firebase('your-firebase-url/data');
var allData = null;
// if you don't need to load the data then just use this variable to increment
var allDataCount = 0;
// be wary since this is an async call, it may not be available for your
// function below. Look into using a deferred instead.
firebaseData.once('value', function(snapshot) {
allData = snapshot.val();
allDataCount = snapshot.numChildren(); // this is the index to increment off of
});
// assuming this is some click event that adds the data it should
function funct1(evt) {
var gameName = $('#nameInput').val();
var medalCount = $('#medalsInput').val();
var bool = $('#boolInput').is(':checked');
firebaseData.child('/' + allDataCount).set({
games: gameName,
medals: medalCount,
summergames: bool
});
allDataCount += 1; // increment since we still don't have the reference
};
For more information about managing lists in Firebase, there's a good article in the Firebase API Docs. https://www.firebase.com/docs/managing-lists.html
Related
I'm currently facing a difficulty in my codes.
First i have an array of objects like this [{Id:1, Name:"AML", allowedToView:"1,2"}, {Id:2, Name:"Res", allowedToView:"1"}...] which came from my service
I assign it in variable $scope.listofResource
Then inside of one of my objects I have that allowedToView key which is a collection of Id's of users that I separate by comma.
Then I have this code...
Javascript
$scope.listofResource = msg.data
for (var i = 0; i < msg.data.length; i++) {
First I run a for loop so I can separate the Id's of every user in allowedToView key
var allowed = msg.data[i].allowedToView.split(",");
var x = [];
Then I create a variable x so I can push a new object to it with a keys of allowedId that basically the Id of the users and resId which is the Id of the resource
for (var a = 0; a < allowed.length; a++) {
x.push({ allowedId: allowed[a], resId: msg.data[i].Id });
}
Then I put it in Promise.all because I have to get the Name of that "allowed users" base on their Id's using a service
Promise.all(x.map(function (prop) {
var d = {
allowedId: parseInt(prop.allowedId)
}
return ResourceService.getAllowedUsers(d).then(function (msg1) {
msg1.data[0].resId = prop.resId;
Here it returns the Id and Name of the allowed user. I have to insert the resId so it can pass to the return object and it will be displayed in .then() below
return msg1.data[0]
});
})).then(function (result) {
I got the result that I want but here is now my problem
angular.forEach(result, function (val) {
angular.forEach($scope.listofResource, function (vv) {
vv.allowedToView1 = [];
if (val.resId === vv.Id) {
vv.allowedToView1.push(val);
I want to update $scope.listofResource.allowedToView1 which should hold an array of objects and it is basically the info of the allowed users. But whenever I push a value here vv.allowedToView1.push(val); It always updates the last object of the array.
}
})
})
});
}
So the result of my code is always like this
[{Id:1, Name:"AML", allowedToView:"1,2", allowedToView:[]}, {Id:2, Name:"Res", allowedToView:"1", allowedToView:[{Id:1, Name:" John Doe"}]}...]
The first result is always blank. Can anyone help me?
Here is the plunker of it... Plunkr
Link to the solution - Plunkr
for (var i = 0; i < msg.length; i++) {
var allowed = msg[i].allowedToView.split(",");
msg[i].allowedToView1 = [];
var x = [];
Like Aleksey Solovey correctly pointed out, the initialization of the allowedToView1 array is happening at the wrong place. It should be shifted to a place where it is called once for the msg. I've shifted it to after allowedToView.split in the first loop as that seemed a appropriate location to initialize it.
I am new to VueJs and working on a small nutrition app. Currently, we want to make food recs based on certain nutrients.
The JS is as follows:
recommendFood: function() {
this.recs = {};
var _this = this;
var getItem = function(ndbno,i,nid) {
_this.$http.get('http://127.0.0.1:3000/item?ndbno=' + ndbno).then(function(response) {
var someData = response.body;
var nutrients = someData.report.food.nutrients;
var item = someData.report.food;
item = this.addNutrientsToItem(item, nutrients);
this.recs[nid].push(item);
});
};
for (var i=0; i<this.low_nutrients.length; i++) {
this.low_nutrients[i].recs = [];
this.recs[this.low_nutrients[i].id] = [];
for (var k=0; k<this.low_nutrients[i].food_map.length; k++) {
var ndbno = this.low_nutrients[i].food_map[k];
getItem(ndbno,i,this.low_nutrients[i].id);
}
}
console.log(this.recs)
}
I want this.recs to be an object with attributes that are equivalent to a nutrient id (that we store). Each nutrient has a food_map array attached to the object that contains id's of foods that would be the recommendations. I need to send those id's (ndbno) to the http request to receive the object of that food recommendation (item).
The this.recs object actually populates correctly (despite there probably being a better way to write my code), however since it's waiting on the loop and promise, the html renders before the object is complete. Therefore, my html is blank. How can I display the recs on the html once they are updated on the promise result?
Here is my HTML:
<div v-for="(nutrient, idx) in low_nutrients">
<h2>{{nutrient.name}}</h2>
<div>Recommended Foods:</div>
<div>
<div>Recs:</div>
<div v-for="rec in recs[nutrient.id]">{{rec}}</div>
</div>
</div>
The desired object this.recs should look something like this (and it does show this in the console):
this.recs = {
291: [{},{},{}],
316: [{},{},{}]
}
The problem is that this.recs starts out empty. Vue cannot detect property additions, so you have to use set to tell it that new properties have been added (and to make those properties reactive).
Or you can re-assign a new object to this.recs rather than modifying its contents.
Basically what i'm doing, is trying to create my own steam market JSON, by HTML parsing.
Example of how I'm currently doing that :
var url = 'http://steamcommunity.com/market/search?appid=730'
var itemDiv = $("<div></div>")
$.get(url).success(function(r){
data = $(r).find('stuff i need')
itemDiv.append(data)
})
and now say I wanted to find names of the items in the div, i would do something like :
itemDiv.find('x').each(function(){
var name = $(this).find("y").text()
// console.log(name) [or do whatever is needed ect]
})
As I mentioned before, I need to return objects based on that data in the format of:
var item = {name:"",price:0}
However, things like price will always be changing.
Based on the data thats in the div, the final product would look along the lines of :
var x = {name:"a",price:1}
var x2 = {name:"a2",price:2}
How do I go about doing this? I thought maybe i could store the data in an array, and then do something like
for(x in y){
return object
}
or something along those lines.
Sorry if this seems like a bonehead question, I'm pretty new to javascript.
clarification: i'm trying to figure out how to return multiple objects based on the data inside the div.
Here is the code that builds an array of objects based on two arrays (assuming they are of equal length).
function buildStocks() {
// Names and prices can also be passed as function arguments
var names = ['a', 'b', 'c'];
var prices = [1, 2, 3];
var result = []; // Array of these objects
for (var i = 0; i < names.length; i++) {
result.push({
name: names[i],
price: prices[i]
});
}
return result;
}
I am programming a chat system. I always make a Localstorage variable when a new chat is opened. Created like this:
localStorage.setItem("chat_"+varemail, data);
Now i want to check how many of them I have so something like:
"chat_"+... count.
How can I do this?
You'd grab the array of keys of the localStorage object, and use Array.filter to grab only the items starting with "chat_":
var length = Object.keys(localStorage).filter(function(key) {
return /^chat_.+/.test(key);
}).length;
Here's a JSFiddle
Try something like this, loop through all items in localStorage and match against your pattern
function getChatCount(){
var chatCount = 0;
for(item in localStorage){
if(item.indexOf('chat_') > -1) chatCount++;
}
return chatCount;
}
Local storage is based on key, value pairs. AFAIK, you wouldn't be able to retrieve all values with a certain prefix.
One potential solution would be to store an object that contains these. Based on your needs you could store the objects in an array or object and then retrieve the entire set and find the count.
For example:
var chats = { count: 0 };
chats["chat_"+varemail] = data;
chats.count += 1;
localStorage.setItem('chats', data);
Then if you want a count, you would retrieve the object:
var chats = localStorage.getItem('chats');
//chats.count would give you the count.
Although, this would mean you have to manually maintain the count variable when adding or removing data. If you don't need the indexing ability, you could add the chats to an array and store that.
EDIT: It is possible to find properties with a certain prefix, as seen in an answer to this question.
I would offer to convert to localStorage.setItem("chat", JSON.stringify(stack)), where stack is an array of chat objects. This way, you have access to an array of chats which you can count, search within, etc.
Something like:
var chatStore =
{
Count: function () {
var stack = JSON.parse(localStorage.getItem("chats"));
if (!stack)
return 0;
return stack.length;
},
Peek: function () {
var stack = JSON.parse(localStorage.getItem("chats"));
if (!stack)
stack = [];
if (stack.length > 0)
return stack.pop();
},
Push: function (token) {
var stack = JSON.parse(localStorage.getItem("chats"));
if (!stack)
stack = [];
stack.push(token);
localStorage.setItem("chats", JSON.stringify(stack));
},
// more methods to you might wish to implement: search, insert, etc.
}
// usage:
chatStore.Push(chatObject); // sets the last chat
chatStore.Peek(); // gets the last chat
I am trying to break a javascript object in to small array so that I can easily access the innerlevel data whenever I needed.
I have used recursive function to access all nodes inside json, using the program
http://jsfiddle.net/SvMUN/1/
What I am trying to do here is that I want to store these in to a separate array so that I cn access it like
newArray.Microsoft= MSFT, Microsoft;
newArray.Intel Corp=(INTC, Fortune 500);
newArray.Japan=Japan
newArray.Bernanke=Bernanke;
Depth of each array are different, so the ones with single level can use the same name like I ve shown in the example Bernanke. Is it possible to do it this way?
No, you reduce the Facets to a string named html - but you want an object.
function generateList(facets) {
var map = {};
(function recurse(arr) {
var join = [];
for (var i=0; i<arr.length; i++) {
var current = arr[i].term; // every object must have one!
current = current.replace(/ /g, "_");
join.push(current); // only on lowest level?
if (current in arr[i])
map[current] = recurse(arr[i][current]);
}
return join;
})(facets)
return map;
}
Demo on jsfiddle.net
To get the one-level-data, you could just add this else-statement after the if:
else
map[current] = [ current ]; // create Array manually
Altough I don't think the result (demo) makes much sense then.