I am trying to incorporate a micro template into a plugin I am building. I have gotten everything good and all, but I am having issues when it comes to the nested array in the data. Thank you very much in advance for your help. Here is the stripped code:
var locations = [{
"name": "Disneyland California",
"address": "1313 North Harbor Boulevard"
},
{
"name": "Walt Disney World Resort",
"address": "1503 Live Oak Ln"
}],
tmplData = [{
location: locations[0],
foo: "bar"
}],
template = "Shipping From:<br><b>{{location.name}}, {{foo}}",
attachTemplateToData;
attachTemplateToData = function(template, data) {
var i = 0,
len = data.length,
fragment = '';
function replace(obj) {
var t, key, reg;
for (key in obj) {
reg = new RegExp('{{' + key + '}}', 'ig');
t = (t || template).replace(reg, obj[key]);
}
return t;
}
for (; i < data.length; i++) {
fragment += replace(data[i]);
}
console.log(fragment);
};
attachTemplateToData(template, tmplData);
Logs:
bar,{{location.name}}
As you can see in the console.log that 'foo' comes out just fine, but I also need to get the 'location.name' ("Disneyland California") to render as well. I know its going to be a nested loop, but I cannot for the life of me figure out the syntax. BTW, the templating solution came from here: http://net.tutsplus.com/tutorials/javascript-ajax/create-a-makeshift-javascript-templating-solution/
Thanks!
EDIT:::
I am looking to make ANY property of the locations object able to be put into the template. So for instance if the user decided they want to add locations.city or locations.foo to the array, then in the template, they would just have to go {{location.city}} or {{location.foo}}.
I HAVE been able to achieve this through the use of jQuery's tmpl plugin, but I don't need all of what that has to offer. I would like a VERY stripped version like I have, to only deal with the said instances. Here is what I did with the tmpl plugin (which works):
tmplData = [{
locations: settings.locations[i]
}];
var tmplMarkup = "Shipping From:<br><b>${locations.name}, ${locations.city}, ${locations.state}</b>";
$.template("deTemplate", tmplMarkup);
$.tmpl("deTemplate", tmplData).appendTo("#deResults");
What you need is to change template recognition to match not only {{prop}} in your matching code , but also {{prop.something}}
you can do this adding another if statement with new regexp.
instead of this:
var locations = [{
"name": "Disneyland California",
"address": "1313 North Harbor Boulevard"
},
{
"name": "Walt Disney World Resort",
"address": "1503 Live Oak Ln"
}],
tmplData = [{
location: locations[0],
foo: "bar"
}],
template = "Shipping From:<br><b>{{location.name}}, {{foo}}",
attachTemplateToData;
Try this:
var locations = [{
name: "Disneyland California",
address: "1313 North Harbor Boulevard"
},
{
name: "Walt Disney World Resort",
address: "1503 Live Oak Ln"
}],
tmplData = [{
location: locations[0].name,
foo: "bar"
}],
template = "Shipping From:<br><b>{{location}}, {{foo}}",
attachTemplateToData;
Really it is just the .name needs to be about 4 lines up! :)
Thank you for your input vittore, I have finally figured out the code. Here is the extra if statement and regEx that I needed to have, also I found that I need the .hasOwnProperty function in there too:
for(subKey in obj[key]){
if (obj[key].hasOwnProperty(subKey)) {
reg = new RegExp('{{'+key+'.'+subKey+'}}');
t = (t || template).replace(reg, obj[key][subKey]);
}
}
Here is the completed code:
var locations = [{
"name": "Disneyland California",
"address": "1313 North Harbor Boulevard"
},
{
"name": "Walt Disney World Resort",
"address": "1503 Live Oak Ln"
}],
tmplData = [{
location: locations[1],
foo: "bar"
}],
template = "Shipping From:<br><b>{{location.address}}, {{foo}}",
attachTemplateToData;
attachTemplateToData = function(template, data) {
var i = 0,
j = 0,
len = data.length,
fragment = '';
function replace(obj) {
var t, key, subKey, subSubKey, reg;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
reg = new RegExp('{{' + key + '}}', 'ig');
t = (t || template).replace(reg, obj[key]);
for(subKey in obj[key]){
if (obj[key].hasOwnProperty(subKey)) {
reg = new RegExp('{{' + key + '.' + subKey + '}}','ig');
t = (t || template).replace(reg, obj[key][subKey]);
}
}
}
}
return t;
}
for (; i < data.length; i++) {
fragment += replace(data[i]);
}
console.log(fragment);
};
attachTemplateToData(template, tmplData);
Related
I have a jquery array.In here i want to remove WORLD NEWS item.
My array comes like this,
[Object { NewsType="WORLD NEWS", NoOfHours=2},
Object { NewsType="LOCAL NEWS", NoOfHours=1},
Object { NewsType="SPORTS NEWS", NoOfHours=2}]
i have tried it like this,
var remItem ="WORLD" ;
NewsArray.splice($.inArray(remItem, NewsArray), 1);
but in here i hardcoded news,it's not good because sometimes it comes as a world or global or any other similar name.
How do i solve this problem?
Your jSON structure should not contain = instead it should be in key:value pair.You can filter this by using grep fun
var data= [
{ NewsType:"WORLD NEWS", NoOfHours:2},
{ NewsType:"LOCAL NEWS", NoOfHours:1},
{ NewsType:"SPORTS NEWS", NoOfHours:2}
]
var target = "WORLD NEWS";
data = jQuery.grep(data, function(e){
return e.NewsType != target;
});
try replacing
NewsArray.splice($.inArray(remItem, NewsArray), 1);
with
NewsArray = NewsArray.filter(function(val){return val.NewsType.indexOf(remItem)== -1});
This will filter out items which has WORLD in it.
Try using filter
var obj = [{ NewsType:"WORLD NEWS", NoOfHours:2},{ NewsType:"LOCAL NEWS", NoOfHours:1},{ NewsType:"SPORTS NEWS", NoOfHours:2}];
var rez = obj.filter(function(v){
return v.NewsType != "WORLD NEWS";
});
Reffer this link
var y = ['WORLD NEWS','LOCAL NEWS', 'SPORTS NEWS']
var removeItem = 'WORLD NEWS';
y = jQuery.grep(y, function(value) {
return value != removeItem;
});
You can use Array.prototype.indexOf(), $.grep()
arr.splice(arr.indexOf($.grep(arr, function(obj) {
return obj.NewsType === "WORLD NEWS"
})[0]), 1);
var arr = [{
NewsType: "WORLD NEWS",
NoOfHours: 2
}, {
NewsType: "LOCAL NEWS",
NoOfHours: 1
}, {
NewsType: "SPORTS NEWS",
NoOfHours: 2
}];
arr.splice(arr.indexOf($.grep(arr, function(obj) {
return obj.NewsType === "WORLD NEWS"
})[0]), 1);
console.log(JSON.stringify(arr, null, 2))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
I have 2 object arrays. The 1st is an array of managers. The 2nd is an array of selected managers from the 1st array. The difference is I added a property selected: true. I need to now replace the the managers in the first array with selected managers. I am doing this with an AngularJS service I created. I'm sure there is much simpler solution so I'm open to suggestions. JavaScript, jQuery, lodash, LINQ.js are good.
I have a plunker and I have displayed the result I need. Notice the manager that does not have the selected:true property.
plunker
var app = angular.module("mainModule", []);
var MainController = function($scope, service) {
var eventUsers = [
{
"event_Users_ID":1009,"event_ID":11,"user_ID":"15e640c1-a481-4997-96a7-be2d7b3fcabb"
},{
"event_Users_ID":1010,"event_ID":11,"user_ID":"250a19be-e661-4c04-9a50-c84b0e7349b7"
},{
"event_Users_ID":1011,"event_ID":11,"user_ID":"4cada7f0-b961-422d-8cfe-4e96c1fc11dd"
},{
"event_Users_ID":1013,"event_ID":11,"user_ID":"a3125317-5deb-426d-bbb1-06d3bd4ebaa6"
}];
var managers = [
{
"id": "15e640c1-a481-4997-96a7-be2d7b3fcabb",
"fullName": "Kul Srivastva"
},{
"id": "250a19be-e661-4c04-9a50-c84b0e7349b7",
"fullName": "Todd Brothers"
}, {
"id": "4cada7f0-b961-422d-8cfe-4e96c1fc11dd",
"fullName": "Rudy Sanchez"
}, {
"id": "79823c6d-de52-4464-aa7e-a15949fb25fb",
"fullName": "Mike Piehota",
}, {
"id": "a3125317-5deb-426d-bbb1-06d3bd4ebaa6",
"fullName": "Nick Broadhurst"
}];
$scope.result = service.eventUserMatch(eventUsers, managers);
};
function service() {
var vm = this;
vm.eventUserMatch = function (eventUsers, managers) {
var arry = [];
arry = $.map(eventUsers, function (eventUser) {
var manager = $.grep(managers, function (user) {
return user.id === eventUser.user_ID;
})[0];
eventUser.id = manager.id;
eventUser.fullName = manager.fullName;
eventUser.selected = true;
return eventUser;
});
return arry;
};
}
app.controller("MainController", MainController);
app.service('service', service);
You can use Array#map.
// Get all the event user IDs in an array
var eventUserIds = eventUsers.map(e => e.user_ID);
// Iterate over managers
managers = managers.map(e => {
// If manager is present in the event users, `select` it
if (eventUserIds.indexOf(e.id) !== -1) {
e.selected = true;
}
return e;
});
var eventUsers = [{
"event_Users_ID": 1009,
"event_ID": 11,
"user_ID": "15e640c1-a481-4997-96a7-be2d7b3fcabb"
}, {
"event_Users_ID": 1010,
"event_ID": 11,
"user_ID": "250a19be-e661-4c04-9a50-c84b0e7349b7"
}, {
"event_Users_ID": 1011,
"event_ID": 11,
"user_ID": "4cada7f0-b961-422d-8cfe-4e96c1fc11dd"
}, {
"event_Users_ID": 1013,
"event_ID": 11,
"user_ID": "a3125317-5deb-426d-bbb1-06d3bd4ebaa6"
}];
var managers = [{
"id": "15e640c1-a481-4997-96a7-be2d7b3fcabb",
"fullName": "Kul Srivastva"
}, {
"id": "250a19be-e661-4c04-9a50-c84b0e7349b7",
"fullName": "Todd Brothers"
}, {
"id": "4cada7f0-b961-422d-8cfe-4e96c1fc11dd",
"fullName": "Rudy Sanchez"
}, {
"id": "79823c6d-de52-4464-aa7e-a15949fb25fb",
"fullName": "Mike Piehota",
}, {
"id": "a3125317-5deb-426d-bbb1-06d3bd4ebaa6",
"fullName": "Nick Broadhurst"
}];
var eventUserIds = eventUsers.map(e => e.user_ID);
managers = managers.map(e => {
if (eventUserIds.indexOf(e.id) !== -1) {
e.selected = true;
}
return e;
})
console.log(managers);
document.getElementById('result').innerHTML = JSON.stringify(managers, 0, 4);
<pre id="result"></pre>
would this work? Loop through the new array of managers, find the index using lodash of a matching manager object in the old manager array and replace it in the old manager array with the manager from the new manager array if found?
There's probably a more efficient way to write a solution to this but assuming I'm understanding your problem correctly I believe this should work? Can't test as I'm at work currently.
for(var i=0; i < SelectedManagersArray.length; i++){
var index = _.findIndex(OldManagersArray, {id: SelectedManagersArray[i].id, fullName: selectedManagersArray[i].fullName);
//I believe lodash returns a -1 if a matching index isn't found.
if(index !== -1){SelectedManagersArray[index] = OldManagersArray[i]}
}
Simple implementation:
for(var i = 0; i < eventUsers.length; i++) {
for(var j = 0; j < managers.length; j++) {
if(eventUsers[i].user_ID === managers[j].id) {
managers[j].selected = true;
}
}
}
As you said, I do think there may be an easier way to do this.
I advise you to pick a look to SugarJs which is a JavaScript library that extends native objects with so helpful methods.
In your case the doc on Arrays.
For me, it helps a lot dealing with a lot of native JavaScript Object (JSON).
I need to convert the following JSON data:
var response = {
"data": {
"List": [
{
"Name": "Mary",
"state": "AZ",
"Matriculation": "complete",
"Graduation": "complete",
"Masters": "complete",
"Phd": "notStarted"
},
{
"Name": "Stephanie",
"state": "CT",
"Matriculation": "complete",
"Graduation": "complete",
"Masters": "complete",
"Phd": "notStarted"
},
{
"Name": "John",
"state": "CT",
"Matriculation": "complete",
"Graduation": "planning",
"Masters": "notStarted",
"Phd": "notStarted"
}]
}
}
into the following using jQuery:
[
{
"state":"AZ",
"Matriculation":[
{
"Name":"Mary",
"status":"complete"
}
],
"Graduation":[
{
"Name":"Mary",
"status":"complete"
}
],
"Masters":[
{
"Name":"Mary",
"status":"complete"
}
],
"Phd":[
{
"Name":"Mary",
"status":"notStarted"
}
]
},
{
"state":"CT",
"Matriculation":[
{
"Name":"Stephanie",
"status":"complete"
},
{
"Name":"John",
"status":"complete"
}
],
"Graduation":[
{
"Name":"Stephanie",
"status":"complete"
},
{
"Name":"John",
"status":"planning"
}
],
"Masters":[
{
"Name":"Stephanie",
"status":"complete"
},
{
"Name":"John",
"status":"notStarted"
}
],
"Phd":[
{
"Name":"Stephanie",
"status":"notStarted"
},
{
"Name":"John",
"status":"notStarted"
}
]
}
]
This is what I have tried so far with zero progress.
I tried to accomplish this for one state first.
This is the fiddle:
http://jsfiddle.net/sqgdyk6f/
Any guidance is appreciated.
I am new to JSON manipulation.
Thanks in advance!
First thing you should do is analyze your source format, and your destination format.
Your source format is just an array of objects of individual people.
Your destination format is an object that groups the people by state
and into certain categories.
Next, think about how you can get the source into this destination.
You're going to want to iterate over each individual person in the source, and try to add it to your array of states. Now, I'll say your destination format is a bit peculiar, but by writing a couple of helper functions, you can achieve that format.
Take a look at your destination format again. It's an array of objects. Part of each object in that array is a property called state that has a value for the state that object represents. You're going to want a function that can look through this array for a specific state, and return the existing object for you. If the state doesn't exist, it should add a new entry to the array for you and return that.
Since JSON just means JavaScript Object Notation, and you are actually working with JavaScript objects, you should create an object that models each entry of your destination array. I'm going to call these StateSummary.
function StateSummary(state) {
this.state = state;
this.Matriculation = [];
this.Graduation = [];
this.Masters = [];
this.Phd = [];
}
Can you see how this object represents each entry in your destination array?
Now that you have an object that models each entry, we need a function that can check to see if an entry for a certain state already exists. If it exists, it will return that object. If it doesn't exist, it will add a new object to the array, and return this new object.
function addOrGetState(array, state) {
for (var i = 0; i < array.length; i++) {
var obj = array[i];
if (obj.state === state)
return obj;
}
//If the function got here, then it didn't find a matching state.
var obj = new StateSummary(state);
array.push(obj); //Add the new object to the array.
return obj; //Return the new object.
}
So, now you can get an entry by state from your destination array, and you can create new entries.
Go ahead and create a function that will add a person to a StateSummary object.
function addPersonToStateSummary(person, stateSummary) {
stateSummary.Matriculation.push({ Name: person.Name, status: person.Matriculation });
stateSummary.Graduation.push({ Name: person.Name, status: person.Graduation});
stateSummary.Masters.push({ Name: person.Name, status: person.Masters});
stateSummary.Phd.push({ Name: person.Name, status: person.Phd});
}
The last piece is iterating over the source array, and massaging that data into your destination array.
var sourceArray = response.data.List; //You provided this.
var destinationArray = []; //Allocate a new array to put stuff in.
for (var i = 0; i < sourceArray.length; i++) {
var person = sourceArray[i]; //Each entry of the source array represents a person.
var stateSummary = addOrGetState(destinationArray, person.state);
addPersonToStateSummary(person, stateSummary);
}
This should give you what you are looking for. I hope this breakdown teaches you how to think about the problem in an analytical way, breaking its steps down first, and then solving them with code.
Here is a demo:
var response = {
"data": {
"List": [{
"Name": "Mary",
"state": "AZ",
"Matriculation": "complete",
"Graduation": "complete",
"Masters": "complete",
"Phd": "notStarted"
}, {
"Name": "Stephanie",
"state": "CT",
"Matriculation": "complete",
"Graduation": "complete",
"Masters": "complete",
"Phd": "notStarted"
}, {
"Name": "John",
"state": "CT",
"Matriculation": "complete",
"Graduation": "planning",
"Masters": "notStarted",
"Phd": "notStarted"
}]
}
};
function StateSummary(state) {
this.state = state;
this.Matriculation = [];
this.Graduation = [];
this.Masters = [];
this.Phd = [];
}
function addOrGetState(array, state) {
for (var i = 0; i < array.length; i++) {
var obj = array[i];
if (obj.state === state)
return obj;
}
//If the function got here, then it didn't find a matching state.
var obj = new StateSummary(state);
array.push(obj); //Add the new object to the array.
return obj; //Return the new object.
}
function addPersonToStateSummary(person, stateSummary) {
stateSummary.Matriculation.push({
Name: person.Name,
status: person.Matriculation
});
stateSummary.Graduation.push({
Name: person.Name,
status: person.Graduation
});
stateSummary.Masters.push({
Name: person.Name,
status: person.Masters
});
stateSummary.Phd.push({
Name: person.Name,
status: person.Phd
});
}
var sourceArray = response.data.List; //You provided this.
var destinationArray = []; //Allocate a new array to put stuff in.
for (var i = 0; i < sourceArray.length; i++) {
var person = sourceArray[i]; //Each entry of the source array represents a person.
var stateSummary = addOrGetState(destinationArray, person.state);
addPersonToStateSummary(person, stateSummary);
}
document.getElementById('result').innerHTML = JSON.stringify(destinationArray);
<div id="result"></div>
Given json like this :
{ "rss": {
"page": 1,
"results": [{
"type": "text",
"$": 10
}],
"text": [{
"content": "Lorem ipsum dolor sit amet.",
"author": {
"name": "Cesar",
"email": "cesar#evoria.com"
},
},
{
"content": "Tema Tis rolod muspi merol.",
"author": {
"name": "Cleopatre",
"email": "cleopatre#pyramid.com"
},
}]
}
In javascript, I can retrieve value like this :
var json = JSON.parse(datajson);
$.each(json.text, function(key, val) {
// this one is ok
var content = val['content'];
// this one does not work
var authorname = val['author.name'];
});
Is this a way, given the attribute name in a string format, to retrieve the value of a complex object, for instance json.text[0].author.name?
EDIT
I would like to store the needed attributes in another object like :
[
{ dt: "Text content", dd: "content" },
{ dt: "Author name", dd: "author.name"}
]
You can split your "index" by . and loop over "segments", descending through levels on each iteration.
var obj = {
author : {
name : "AuthorName"
}
}
function get_deep_index(obj, index) {
var segments = index.split('.')
var segments_len = segments.length
var currently_at = obj
for(var idx = 0; idx < segments_len; idx++) {
currently_at = currently_at[segments[idx]]
}
return currently_at
}
console.log(get_deep_index(obj, 'author.name'))
The following should fix the problem.
var authorname = val['author']['name'];
You can also store the object itself as:
var author = val['author'];
And then later on you can index the attributes from that.
console.log(author.name, author.email)
Yent give a good hint in the comments with the eval function. I resolve my needed with this kind of code:
var json = JSON.parse(myjsonasastring);
var descriptiontobeadded = [
{ dt: "Text content", dd: "content" },
{ dt: "Author name", dd: "author.name" }
];
$.each(descriptiontobeadded, function(key, val) {
var dt = '<dt>' + val.dt + '</dt>';
description.append(dt);
var dl = '<dd>' + eval('json.' + val.dd) + '</dd>';
description.append(dl);
});
What is the best way to apply queries (such as regular expressions) on javascript objects to obtain a subset of some array or collection that follow some criteria, are there such plugin for jQuery, or some way to use jQuery or other known js library for this purpose?
for example:
var x=[{ firstName: "Tony",lastName="Mike" }, { firstName: "John", lastName="Jan"}];
var y = ????;//the first names of the objects in x where their last names follow the regular expression : bla-bla-bla
It appears as you are looking for JSONpath or the like.
using jQuery:
var x = [
{ firstName: "Sakher",lastName:"Sawan" },
{ firstName: "John", lastName:"Jan"}
],
y = $(x).map(function(a, obj){
return /^S/.test(obj.lastName) ? obj.firstName : null
});
Note that in some browsers you don't have to use jQuery to do this, as you can just as well use x.map in browsers that have Array.prototype.map (older browsers don't)
You should use some frameworks like dojo for doing these kind of operations.
look at the sample grid
http://dojotoolkit.org/reference-guide/dojox/grid/DataGrid.html
you can do all kind of operations on that.
It seems that you can do it by JS itself:
var re = ...; // regular espression
var y = [....]; // input array
var x = y.filter(function(el) { return re.test(el.firstName) } );
In x you will have filtered array where each element satisfy your conditions.
Check this link.
var jsonArray = [
{ "user": { "id": 100, "screen_name": "d_linq" }, "text": "to objects" },
{ "user": { "id": 130, "screen_name": "c_bill" }, "text": "g" },
{ "user": { "id": 155, "screen_name": "b_mskk" }, "text": "kabushiki kaisha" },
{ "user": { "id": 301, "screen_name": "a_xbox" }, "text": "halo reach" }
]
// ["b_mskk:kabushiki kaisha", "c_bill:g", "d_linq:to objects"]
var queryResult = Enumerable.From(jsonArray)
.Where(function (x) { return x.user.id < 200 })
.OrderBy(function (x) { return x.user.screen_name })
.Select(function (x) { return x.user.screen_name + ':' + x.text })
.ToArray();
// shortcut! string lambda selector
var queryResult2 = Enumerable.From(jsonArray)
.Where("$.user.id < 200")
.OrderBy("$.user.screen_name")
.Select("$.user.screen_name + ':' + $.text")
.ToArray();