Javascript arrays or object - javascript

I wish to grab content from various sources, using different API calls, and collate them all into an object or array with the same format. I am getting stuck with javascript arrays and objects, and none of the examples I find seem to do what I want to do. This is the format I want to store. This is pseudo coded for an example of what I want to achieve
var content = new Object();
getTweets();
getSoundCloud();
display();
function getTweets() {
//first result
content.type = "tweet
content.text = "the text of the tweet"
content.image = "the image from the tweet"
return content;
}
function getSoundCloud() {
//second result
content.type = "soundcloud
content.text = "the name of the song"
content.image = "the image of the song"
return content;
}
function display() {
//for each content
{
$("#container").append(content.text);
}
}
The first result is generated by one function call, and the Second result is generated by a different function call.
I want these functions to add all of the content together into the same format object. Once the object is populated, I wish to iterate it in a different function and display on the screen.
How do I make this object? I have tried it but the data is always the same, ie, overwritten with the same values. In php this would be an associative array perhaps or something like
I want to have an object for each piece of content I have, and can loop through it
content[0].type = "tweet"
content[1].type = "coundcloud"
Any suggestions with examples would be great.
Many Thanks

When you have many of something you should immediately think
I need to store these things in an array.
When your "things" are complex and have various properties/ state, you should immediately think:
I need to create an object to store them.
... so what would be best here is an array of objects. Each function will create objects and add them to content, which we'll switch to an array:
var content = []; // Array
getTweets();
getSoundCloud();
display();
function getTweets() {
var tweet = {}; // This is an object
tweet.type = "tweet";
tweet.text = "The text of the tweet";
tweet.image = "The image of the tweet";
content.push(tweet); // add the object to the array.
}
function getSoundCloud() {
var soundcloudThing = {};
soundcloudThing.type = "soundcloud"
soundcloudThing.text = "the name of the song"
soundcloudThing.image = "the image of the song"
content.push(soundcloudThing);
}
Now when it comes to showing this content, as have an array; the obvious thing to do here is iterate over it;
function display() {
for (var i=0;i<content.length;i++)
{
$("#container").append(content[i].text);
// You can also use content[i].image and content[i].type in here
}
}
Note that [] and {} is literal notation for creating arrays and objects. It's use is favoured over new Array() and new Object().

I have done an example here: http://jsfiddle.net/pdXsA/2/
var content = [];
content.push(getTweets());
content.push(getSoundCloud());
display();
function getTweets() {
return{
type : "tweet",
text : "the text of the tweet",
image : "the image from the tweet"
};
}
function getSoundCloud() {
return{
type : "soundcloud",
text : "the name of the song",
image : "the image of the song"
};
}
function display() {
content.forEach(function(item){
$("#container").append(item.text +"<br/>");
});
}​

content should be an array of objects, each function adds its object into the content array :
var content = []; // empty array
getTweets();
getSoundCloud();
display();
function getTweets() {
content.push ({ //first result
type: "tweet",
text: "the text of the tweet",
image: "the image from the tweet"
});
}
function getSoundCloud() {
content.push ({ //second result
type: "soundcloud",
text: "the name of the song",
image: "the image of the song"
});
}
function display() {
content.forEach (v) {
// code to format the object v appropriately
var vtext = v.type + ' : ' + v.text;
$("#container").append(vtext);
}
}

Actually, just sussed it out like this
var content = {
text: this.text.linkify().linkuser().linktag(),
image: this.profile_image_url,
type: 'tweet'
};
arrayContent.push(content);
I can now loop through it, and each Content and display it!

Related

How do I programmatically build an object from my form data that includes arrays

I need to display some values on a jsp page, grab input from user and send it back to a controller that is using Jackson to bind it to my backing data object. Several rows that I display on the screen are backed by an array and are created with <c:forEach> and I'm generating a path like "blobs[0].id" and "blobs[0].text". When I try to put them into the json object to be sent back to the controller by an ajax call, they aren't being added to the object properly. The property name ends up having "[0]" in the name instead of representing the object at that array index.
<script>
var formData = {};
formData.blobs = [];
formData.blobs[0] = {};
formData.blobs[0].id = "English";
formData.blobs[0].text = "Hello";
formData["blobs[1].id"] = "German";
formData["blobs[1].text"] = "Guten Tag";
console.log(formData);
</script>
ends up looking like {blobs: [0 : {id: "English", text: "Hello"}], blobs[1].id: "German", blobs[1].text: "Guten Tag"} instead of
{blobs: [0 : {id: "English", text: "Hello"}, 1 : {id: "German", text: "Guten Tag"}]}
I am trying to assemble the model thusly:
<script>
function createModel() {
var form = $("#theForm");
var formData = {};
$.each(form, function(i, v){
var input = $(v);
if (input.attr("name")) {
formData[input.attr("name")] = input.val();
}
});
}
</script>
Accessing obj["attr"] is an option to access an object's attribute, so obj["attr[1][22]"] will access an attribute called "attr[1][22]", while accessing obj["attr"][1][22] will access the second element of obj.attr, and the second element's 22th element as well..
The solution will be to access formData["blobs"][0].id or even formData["blobs"][0]["id"]
you can format the string to your needs
$('#yourform').serializeArray() returns an array:
[
{"name":"foo","value":"1"},
{"name":"bar","value":"xxx"},
{"name":"this","value":"hi"}
]
$('#yourform').serialize() returns a string:
"foo=1&bar=xxx&this=hi"
so, in your case
var formData = {};
formData.blobs = [];
$('#yourform').serializeArray().forEach(function(blob){
formData.blobs.push({
id: blob.name,
text: blob.value
});
})

Pouchdb join / link documents

I have pouchdb/couchbase data with equipment that has user assigned to them.
Equipment with _id and in the equipment doc there is a checkedOutBy with the user._id as the value. Within the employee object there is user.name. When I get the equipment objects how do I also get the user.name and display with the equipment.
I have searched and read about map/reduce that uses emit and do not grasp the idea. My code that i wrote from what i learned is:
by the way I am also using Angularjs.
field = "eq::"
this.getAllEquip = function(field){
function map(doc) {
if (doc.checkedOutBy !== undefined) {
emit(doc.checkedOutBy, {empName : doc.name});
}
}
var result = database.query(map, {include_docs: true,
attachments: true,
startkey: field,
endkey: field + '\uffff'})
.catch(function (err) {
//error stuff here
});
return result
};
I don't see where the two docs would get together. What am i missing? My result is empty.
The equipment json looks like:
{checkedOutBy: "us::10015", description: "3P Microsoft Surface w/stylus & power cord", equipId: "SUR1501", purchaseDate: "", rCost: 1000, id:"eq::10001"}
Emlpoyee json:
{"firstname":"Joe","gender":"male","lastname":"Blow","status":"active","title":"office","type":"userInfo","_id":"us::10015","_rev":"2-95e9f34784094104ad24bbf2894ae786"}
Thank you for your help.
Something like this should work, if I understood the question correctly:
//Sample Array of Objects with Equipment
var arr1=[{checkedout:"abc1",desc:"item1",id:1},
{checkedout:"abc2",desc:"item2",id:2},
{checkedout:"abc3",desc:"item3",id:3},
{checkedout:"abc1",desc:"item1",id:4},
{checkedout:"abc4",desc:"item3",id:5},
{checkedout:"abc6",desc:"item3",id:6}];
//Sample array of objects with Employee - the "id" in arr2 matches with "checkout" in arr1
var arr2=[{name:"john",id:"abc1"},
{name:"jack",id:"abc2"},
{name:"alice",id:"abc3"},
{name:"james",id:"abc4"}];
var result = []; //final result array
//loop through equipment array arr1
arr1.forEach(function(obj) {
var tempObj = obj;
var checkedout_id=obj.checkedout;
//do array.find which will return the first element in the array which satisfies the given function. This is absed on the assumption that that the id is unique for employee and there wont bwe multiple employees with same id (which is the "checkedout" field in equipment. If the employee is not found, it will return undefined.
var foundname = arr2.find(function(obj) {
if (obj.id == checkedout_id)
return obj.name
})
//Create the object to be inserted into the final array by adding a new key called "name", based on the result of above find function
if (foundname != undefined) {
tempObj.name=foundname.name
}
else {
tempObj.name = "Not found";
}
result.push(tempObj);
})
This is my Pouchdb solution, thank you Vijay for leading me to this solution.
First I get all my equipment. Then I use Vijay's idea to loop through the array and add the name to the object and build new array. I found there is a need to go into the .doc. part of the object as in obj.doc.checkedOutBy and tempObj.doc.name to get the job done.
$pouchDB.getAllDocs('eq::').then(function(udata){
var result = [];
//loop through equipment array
udata.rows.forEach(function(obj) {
var tempObj = obj;
var checkedout_id=obj.doc.checkedOutBy;
if (checkedout_id != undefined) {
$pouchDB.get(checkedout_id).then(function(emp){
return emp.firstname + " " + emp.lastname
}).then(function(name){
tempObj.doc.name = name;
});
}
result.push(tempObj);
})
in my service I have:
this.get = function(documentId) {
return database.get(documentId);
};
and:
this.getAllDocs = function(field){
return database.allDocs({
include_docs: true,
attachments: true,
startkey: field,
endkey: field + '\uffff'});
};

Turn Observable Array into nested JSON

I'm having a problem getting an array of information stored properly as JSON.
I made a fiddle to illustrate the problem. Enter a set of tags and take a look at the console to see the output.
More explanation:
So I have an input that takes in a comma-separated list of tags, which I then format.
function createTagArray() {
// given an input value of 'tag1, tag2, tag3'
// returns array = ['tag1', 'tag2', 'tag3']
}
I thought what I needed to do next was the following:
loop over the array and create a 'tag' object for each item which also includes an id for the tag and the id of the contact the tag is associated with.
Each object is pushed to tags, an observable array.
function single_tag(id, contactId, tagLabel) {
var self = this;
self.id = id;
self.contactId = contactId;
self.tagLabel = tagLabel;
}
function createTags() {
var array = createTagArray();
for (var i = 0; i < array.length; i++) {
self.tags().push(new single_tag(uuid.generate(), self.contactId, array[i]));
}
}
Then, I converted it into JSON
self.contactInformation = function() {
return ko.toJS({
"id": self.contactId,
"firstname": self.firstname(),
"lastname": self.lastname(),
... other fields ...
"tags": self.tags(),
})
}
But, when I inspect the console output of calling this function, tags is a collection of arrays, not a nice json object.
How do I get it formatted correctly?
I tried this suggestion, and the tag json is structured correctly, but it is stored with escaped quotes, so that seems wrong.
Thanks for all the help!
I would recommend you knockout.mapping plugin for KO, it allow map complicated JSON structure to view model, even without declarations.
From the documentation
Let’s say you have a JavaScript object that looks like this:
var data = {
name: 'Scot',
children: [
{ id : 1, name : 'Alicw' }
]
}
You can map this to a view model without any problems:
var viewModel = ko.mapping.fromJS(data);
Now, let’s say the data is updated to be without any typos:
var data = {
name: 'Scott',
children: [
{ id : 1, name : 'Alice' }
]
}
Two things have happened here: name was changed from Scot to Scott and children[0].name was changed from Alicw to the typo-free Alice. You can update viewModel based on this new data:
ko.mapping.fromJS(data, viewModel);
And name would have changed as expected. However, in the children array, the child (Alicw) would have been completely removed and a new one (Alice) added. This is not completely what you would have expected. Instead, you would have expected that only the name property of the child was updated from Alicw to Alice, not that the entire child was replaced!
...
To solve this, you can specify which key the mapping plugin should use to determine if an object is new or old. You would set it up like this:
var mapping = {
'children': {
key: function(data) {
return ko.utils.unwrapObservable(data.id);
}
}
}
var viewModel = ko.mapping.fromJS(data, mapping);
In the jsfiddle you were using Knockout 3.0 which doesn't have support for textInput. This was added in 3.2. To use version 3.2 you need to use a cdn such as this: http://cdnjs.com/libraries/knockout
There was typeo in your binding. sumbit should be submit.
There was a problem with your constructor for single_tag. id was not used so I removed it:
function single_tag(contactId, tagLabel) {
var self = this;
self.contactId = contactId;
self.tagLabel = tagLabel;
}
Currently also contactId is not set because the observable has not been set to a value.
To convert to JSON you need to use ko.toJSON instead of ko.toJS:
self.contactInformation = function() {
return ko.toJSON({
"firstname": self.firstname(),
"tags": self.tags(),
})
}
Now when the console writes out an array appears:
{
"firstname":"test",
"tags":[
{"tagLabel":"test1"},
{"tagLabel":"test2"},
{"tagLabel":"test3"}
]
}
JsFiddle
So my problem was more basic than I was realizing. I'm using JSON Server to serve up my data, and I was pulling information from two parts of the database (contacts & tags).
When I tried to update my tags, I was trying to apply them to a property that didn't exist on the contact JSON in my database. Posting the tags separately worked though.

JavaScript database correlation

I've been trying to 'correlate' between user picked answers and an object property name so that if the two matches then it will display what is inside.
My program is a recipe finder that gives back a recipe that consists of the ingredients the user picked.
my code currently looks like:
//property are the ingredients and the value are the recipes that contain those ingredients. The map is automatically generated
``var map = {
"pork" : [recipe1, recipe2, ...],
"beef" : [],
"chicken" :[],
}
//this gets the user pick from the dom
var cucumber = specificVegetable[7];
var lemon = specificFruits[0];
//Then this code finds the intersection of the recipe(recipes that use more than one ingredients)
function intersect(array1, array2)
{
return array1.filter(function(n) {
return array2.indexOf(n) != -1
});
}
var recipiesWithLemon = map["lemon"]; **// makes the lemon object is map**
var recipiesWithCucumber = map["cucumber"]; **// makes the cucumber object in map**
//Here is where I am stuck
function check(){
var both = intersect(recipiesWithLemon, recipiesWithCucumber);
if ( cucumber.checked && lemon.checked){
for (var stuff in map){
if(stuff="cucumber" && stuff="lemon"){
return both;
}
}
}
}
check();
so basically what I tried to do was I made my intersect and then if user pick is lemon and cucumber then look at the properties in the map object. if the name of the property equals to the exact string then return both. That was the plan but the code does not work and I'm not sure how to fix it.
My plan is to write code for every possible outcome the user may makes so I need to find the correlation between the user pick and the map which stores the recipe. I realize this is not the most effective way but I'm stumped on how to do it another way.
Thanks for the help.
Im using the open source project jinqJs to simplify the process.
I also changed your map to an array of JSON objects. If you must have the map object not as an array, let me know. I will change the sample code.
var map = [
{"pork" : ['recipe1', 'recipe2']},
{"beef" : ['recipe3', 'recipe4']},
{"peach" :['recipe5', 'recipe6']},
{"carrot" :['recipe7', 'recipe8']}
];
var selectedFruit = 'peach';
var selectedVeggie = 'carrot';
var selections = [selectedFruit, selectedVeggie];
var result = jinqJs().from(map).where(function(row){
for(var f in row) {
if (selections.indexOf(f) > -1)
return true;
}
return false;
}).select();
document.body.innerHTML += '<pre>' + JSON.stringify(result, null, 2) + '</pre><br><br>';
<script src="https://rawgit.com/fordth/jinqJs/master/jinqjs.js"></script>

How to iterate an array of objects and print out one of its properties

I have the following code in a display template in sharepoint, I have an array of objects and I need to have the following result.
Name1
Name2
Name3
So I can replace the default rendering of sharepoint multiple people user field with a tooltip.
However, I dont know how to iterate and then concatenate:
Screenshot:
Code:
// List View - Substring Long String Sample
// Muawiyah Shannak , #MuShannak
(function () {
// Create object that have the context information about the field that we want to change it's output render
var projectTeamContext = {};
projectTeamContext.Templates = {};
projectTeamContext.Templates.Fields = {
// Apply the new rendering for Body field on list view
"Project_x0020_Team": { "View": ProjectTeamTemplate }
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(projectTeamContext);
})();
// This function provides the rendering logic
function ProjectTeamTemplate(ctx) {
var projectTeamValue = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];
//newBodyvalue should have the list of all display names and it will be rendered as a tooltip automaticlaly
return "<span title='" + projectTeamValue + "'>" + newBodyValue + "</span>";
}
You can "map" property values from the projectTeamValue array objects into a new array, then "join" those values together (using ", " as the separator in this example) all in one go:
var newBodyValue = projectTeamValue.map(function(person) {
return person.value;
}).join(", ");
If your projectTeamValue array looked like:
[{ value: "Name1" }, { value: "Name2" }, { value: "Name3" }]
Then newBodyValue would be:
"Name1, Name2, Name3"
jsFiddle Demo
Side note: Array.prototype.map() was not available in IE 8 and below but should work in every other browser.

Categories

Resources