This is part of the JSON i get from foursquare.
JSON
tips: {
count: 2,
groups: [
{
type: "others",
name: "Tips from others",
count: 2,
items: [
{
id: "4e53cf1e7d8b8e9188e20f00",
createdAt: 1314115358,
text: "najjači fitness centar u gradu",
canonicalUrl: "https://foursquare.com/item/4e53cf1e7d8b8e9188e20f00",
likes: {
count: 2,
groups: [
{
type: "others",
count: 2,
items: []
}],
summary: "2 likes"
},
like: false,
logView: true,
todo: {
count: 0
},
user: {
id: "12855147",
firstName: "Damir",
lastName: "P.",
gender: "male",
photo: {
prefix: "https://irs1.4sqi.net/img/user/",
suffix: "/AYJWDN42LMGGD2QE.jpg"
}
}
},
{
id: "4e549e39152098912f227203",
createdAt: 1314168377,
text: "ajd da vidimo hocu li znati ponoviti",
canonicalUrl: "https://foursquare.com/item/4e549e39152098912f227203",
likes: {
count: 0,
groups: []
},
like: false,
logView: true,
todo: {
count: 0
},
user: {
id: "12855147",
firstName: "Damir",
lastName: "P.",
gender: "male",
photo: {
prefix: "https://irs1.4sqi.net/img/user/",
suffix: "/AYJWDN42LMGGD2QE.jpg"
}
}
}]
}]
}
I need to get the last tip text , the user who wrote it and the date when he wrote/post it.
User: Damir P.
Date : 1314115358
Text: najjači fitness centar u gradu
I tried with JQuery and this works to fetch a non-array value:
$.getJSON(url, function(data){
var text= data.response.venue.tips.groups.items.text;
alert(text);
});
But it doesn't work with arrays.
Result : Uncaught TypeError: Cannot read property 'text' of undefined.
Also I tried with $.each, but with no effect.
$.getJSON(url, function(data){
$.each(data.response.venue.tips.groups.items.text, function (index, value) {
console.log(value);
});
});
What am I doing wrong ?
You need to iterate both the groups and the items. $.each() takes a collection as first parameter and data.response.venue.tips.groups.items.text tries to point to a string. Both groups and items are arrays.
Verbose version:
$.getJSON(url, function (data) {
// Iterate the groups first.
$.each(data.response.venue.tips.groups, function (index, value) {
// Get the items
var items = this.items; // Here 'this' points to a 'group' in 'groups'
// Iterate through items.
$.each(items, function () {
console.log(this.text); // Here 'this' points to an 'item' in 'items'
});
});
});
Or more simply:
$.getJSON(url, function (data) {
$.each(data.response.venue.tips.groups, function (index, value) {
$.each(this.items, function () {
console.log(this.text);
});
});
});
In the JSON you specified, the last one would be:
$.getJSON(url, function (data) {
// Get the 'items' from the first group.
var items = data.response.venue.tips.groups[0].items;
// Find the last index and the last item.
var lastIndex = items.length - 1;
var lastItem = items[lastIndex];
console.log("User: " + lastItem.user.firstName + " " + lastItem.user.lastName);
console.log("Date: " + lastItem.createdAt);
console.log("Text: " + lastItem.text);
});
This would give you:
User: Damir P.
Date: 1314168377
Text: ajd da vidimo hocu li znati ponoviti
You're not looping over the items. Try this instead:
$.getJSON(url, function(data){
$.each(data.response.venue.tips.groups.items, function (index, value) {
console.log(this.text);
});
});
I think you need something like:
var text= data.response.venue.tips.groups[0].items[1].text;
try this
$.getJSON(url, function(data){
$.each(data.response.venue.tips.groups.items, function (index, value) {
console.log(this.text);
});
});
Related
So we're working in this system and buildig our own page. We built a form to insert timeline data using a .xwd file. We use javascript to retrieve the data and fill it in a variable to store it. The main page (title:) just has single values, but the actual events should be in an array.
I'm want to use V to fill the array.
$(x_currentPageXML).children().each(function(index, elem){
});
Right now what I have is this and I want to fill the "events" array using the foreach I showed above. Putting the .each inside in the var didn't work and I wouldn't know how else to do it.
var SictTimeline = new function() {
this.loadJS = function () {
$.getScript(x_templateLocation + 'common_html5/js/timeline.js')
.done(function (script, textStatus) {
var make_the_json = $(x_currentPageXML).children().map(function (element) {
return {
title: {
media: {
url: element.getAttribute("url"),
caption: element.getAttribute("tip"),
},
text: {
headline: element.getAttribute("name"),
text: '<p>' + element.getAttribute("text") + '</p>'
}
},
events: {
media: {
url: element.getAttribute("url"),
caption: element.getAttribute("tip"),
},
start_date: {
month: '8',
day: '9',
year: '1963'
},
text: {
headline: element.getAttribute("name"),
text: element.getAttribute("text")
}
}
}
})
var timeline_json = make_the_json; // replace make_the_json() with the JSON object you created
// two arguments: the id of the Timeline container (no '#')
// and the JSON object or an instance of TL.TimelineConfig created from
// a suitable JSON object
window.timeline = new TL.Timeline('timeline-embed', timeline_json);
})
.fail(function (jqxhr, settings, exception) {
console.log('Failed to load the script for the timeline');
});
}
// function called every time the page is viewed after it has initially loaded
this.pageChanged = function() {
}
// function called every time the size of the LO is changed
this.sizeChanged = function() {
}
this.init = function() {
this.loadJS();
// call this function in every model once everything's loaded
x_pageLoaded();
}
}
An example of the xml-file with the values
<?xml version="1.0"?>
<learningObject editorVersion="3" targetFolder="Nottingham" name="Learning Object Title" language="en-GB" navigation="Linear" textSize="12" theme="default" displayMode="fill window" responsive="true">
<SictTimeline linkID="PG1592486441661" name="My page" media="SictTimeline" text="<p>Text for my page</p>
" url="FileLocation + 'media/https___images.genius.com_53c4575fa3f97a8d4b18d69a600afaf0.900x900x1.jpg'" tip="Description for Image 1"></SictTimeline></learningObject>
I guess what you are trying to achieve is to generate an array of objects based on the number (and properties) of elements inside $(x_currentPageXML). For that purpose you need to use the .map() method:
events: $(x_currentPageXML).children().map(function (index, element) {
return {
media: {
url: element.getAttribute("url"),
caption: element.getAttribute("tip"),
},
start_date: {
month: '8',
day: '9',
year: '1963'
},
text: {
headline: element.getAttribute("name"),
text: element.getAttribute("text")
}
}
}).get()
I'm not sure I completely understand the question, but you want to extract stuff from each element in the loop right?
Replace x_currentPageXML with elem inside the loop
var result = []
$(x_currentPageXML).children().each(function (index, elem) {
var make_the_json = {
title: {
media: {
url: elem.getAttribute("url"),
caption: elem.getAttribute("tip"),
},
text: {
headline: elem.getAttribute("name"),
text: '<p>' + elem.getAttribute("text") + '</p>'
}
},
events: [
{
media: {
url: elem.getAttribute("url"),
caption: elem.getAttribute("tip"),
},
start_date: {
month: '8',
day: '9',
year: '1963'
},
text: {
headline: elem.getAttribute("name"),
text: elem.getAttribute("text")
}
}
]
};
result.push(make_the_json)
})
I am Applying filters in my existing saved search, but it's not getting applied.
Can anyone help me what's wrong in this, as I'm new in Suitescripts?
Filters: gender and item are being passed from Suitelet to this Scheduled Script in a parameter:
var slfilters = runtime.getCurrentScript().getParameter({ name: 'custscript_searchfilter_report' });
//
// ─── MAIN FUNCTION───────────────────────────────────────────────────
//
function generateReport() {
var slfilters = runtime.getCurrentScript().getParameter({
name: 'custscript_searchfilter_report'
});
log.debug('slfilters', slfilters);
if (!!slfilters) {
slfilters = JSON.parse(slfilters);
}
log.debug('slfilters2', slfilters);
//var getUser = runtime.getCurrentUser();
var gender = slfilters.isgender
log.debug('gender', gender)
var item = slfilters.isItem
log.debug('item', item)
var item = getItems(item, gender);
log.debug('items table', item)
// return item;
var xmlTemplateFile = file.load(3918);
//var template = script.getParameter({ name: 'custscript_template' });
var renderer = render.create();
renderer.templateContent = xmlTemplateFile.getContents();
var customSources = {
alias: 'searchdata',
format: render.DataSource.JSON,
data: JSON.stringify({
value: item,
})
};
renderer.addCustomDataSource(customSources);
var xml = renderer.renderAsString();
var pdf = render.xmlToPdf({
"xmlString": xml
});
email.send({
author: 317,
recipients: 'aniswtf#gmail.com',
subject: 'Item Report',
body: 'Report Generated: ',
attachments: [pdf]
});
}
//
// ─── SEARCH ───────────────────────────────────────────────────
//
function getItems(item, gender) {
try {
var itemSearch = search.load({
id: 'customsearch_mx_itemsearch'
});
log.error('itemSearch', itemSearch)
var defaultFilters = itemSearch.filters;
var arrFilters = [];
arrFilters.push(search.createFilter({
name: 'custitem5', //gender
operator: 'anyof',
values: gender
}));
arrFilters.push(search.createFilter({
name: 'itemid',
operator: 'anyof',
values: item
}));
defaultFilters = defaultFilters.concat(arrFilters);
log.error('Updated Filters', defaultFilters)
var results = itemSearch.run().getRange({
start: 0,
end: 150
});
results.map(function(x) {
return {
'category': x.getText({
name: "custitem10",
join: "parent"
}),
'season': x.getValue({
name: "custitem11",
join: "parent"
}),
'riselabel': x.getValue({
name: "custitem_itemriselabel",
join: "parent"
}),
'fit': x.getValue({
name: "custitem9",
join: "parent"
}),
'name': x.getValue({ //sku
name: "itemid",
join: "parent"
}),
'style': x.getValue({
name: "custitem8",
join: "parent"
}),
'inseam': x.getValue({
name: "custitem7",
join: "parent"
}),
'wash': x.getValue({
name: "custitem_washname",
join: "parent"
}),
};
});
return results;
} catch (e) {
log.error('error in getItems', e)
}
}
return {
execute: execute
};
});
In SuiteScript 1.0 there was a nlobjSearch method "setFilters". SuiteScript 2.0 does not seem to have an equivalent but you still need to somehow set the filters. It looks like that is the missing step. Perhaps try to push the new filters onto/in place of the current search filters with
itemSearch.filters.push(defaultFilters);
not sure if it'd be desired to then save the search or not. I hope that helps
I am writing a function to return an id based on a few various things aligning. The code mostly works except that because there is no break; for a forEach. I believe I need to use a different filter or find option on the array.
function getDefaultId(prod) {
var defaultId;
prod.images.forEach( function(image) {
defaultId = image.isPrimary ? image.id : undefined;
});
return defaultId;
}
var prod.images = [
0: {
isPrimary: false,
id: 1234
},
1: {
isPrimary: true,
id: 1235
},
2: {
isPrimary: false,
id: 1236
}
]
Essentially I'm trying to return the corresponding id for isPrimary. The result should be 1236 but I'm getting undefined because the forEach is not breaking and thus is resetting the variable to undefined on the next iteration.
You could use Array#some and exit early.
function getDefaultId(prod) {
var defaultId;
prod.images.some(function (image) {
if (image.isPrimary) {
defaultId = image.id;
return true;
}
});
return defaultId;
}
var prod = { images: [{ isPrimary: false, id: 1234 }, { isPrimary: true, id: 1235 }, { isPrimary: false, id: 1236 } ]};
console.log(getDefaultId(prod));
var images = [
{
isPrimary: false,
id: 1234
},
{
isPrimary: true,
id: 1235
},
{
isPrimary: false,
id: 1236
}
]
let result = images.filter(img => img.isPrimary === true)
console.log(result)
You could use .filter() and to get an array of objects which have isPrimary as true, and then return the id of the first item found like so:
function getDefaultId(prod) {
var primaryImg = prod.images.filter(function(img) {
return img.isPrimary;
});
return primaryImg[0].id;
}
var prod = {};
prod.images = [{isPrimary: false, id: 1234 }, {isPrimary: true, id: 1235}, {isPrimary: false, id: 1236}];
console.log(getDefaultId(prod));
Give it a try using map.
var images = [
{
isPrimary: false,
id: 1234
},
{
isPrimary: true,
id: 1235
},
{
isPrimary: false,
id: 1236
}
];
function getDefaultId() {
var defaultId;
images.map(function (image) {
if (image.isPrimary) {
defaultId = image.id;
}
});
return defaultId;
}
console.log(getDefaultId());
I am trying to loop through the results from a Find() Mango Query and make a all to another function to get extra data to use in my report.
I am looping a list of patient documents from a Find() query but I want to pull in the "last visit" from another list of "visit" documents by calling a function that performs a query but I am having problems.
I can call the function "Get_Static_Value()" and it will return a value however when I send the Patient_ID to the function "Get_Last_Visit(Patient_ID)" then the value comes back as "undefined" although the function is called and will write the "Vist_Date" to the console.
I believe my issue is caused because the promise in the query is not resolving but I am unsure of the syntax to get the value back into my loop once the function has processed.
I read the documement https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html and in the section "Rookie mistake #2: WTF, how do I use forEach() with promises?" I think it identifies my problem with the syntax:
db.allDocs({include_docs: true}).then(function (result) {
return Promise.all(result.rows.map(function (row) {
return db.remove(row.doc);
}));
}).then(function (arrayOfResults) {
// All docs have really been removed() now!
});
However the code above is for alldocs and not find() so I am a little bit stuck on how I process the same method on results from a Find() query.
I have created a JSfiddle to show my code and demonstrate my issue.
https://jsfiddle.net/movitico/gkb89uyf/
// Create the Database
var db = new PouchDB('patient_test');
// Add Patient Documents
function Add_Patients() {
db.bulkDocs([{
_id: '1',
type: 'patient',
Patient_Name: 'Patient 1',
Patient_Status: 'Active'
},
{
_id: '2',
type: 'patient',
Patient_Name: 'Patient 2',
Patient_Status: 'Active'
},
{
_id: '3',
type: 'patient',
Patient_Name: 'Patient 3',
Patient_Status: 'Active'
}
]);
}
function Add_Visits() {
// Add Visit Documents
db.bulkDocs([{
_id: 'v1',
type: 'visit',
Patient_ID: '1',
Visit_Date: "06/01/2018"
},
{
_id: 'v2',
type: 'visit',
Patient_ID: '1',
Visit_Date: "05/01/2018"
},
{
_id: 'v3',
type: 'visit',
Patient_ID: '1',
Visit_Date: "02/22/2018"
},
{
_id: 'v4',
type: 'visit',
Patient_ID: '2',
Visit_Date: "02/22/2014"
},
{
_id: 'v5',
type: 'visit',
Patient_ID: '2',
Visit_Date: "02/22/2000"
},
{
_id: 'v6',
type: 'visit',
Patient_ID: '2',
Visit_Date: "02/22/1987"
}
]);
}
function Load_Patients() {
$('#patient_list').empty();
db.createIndex({
index: {
fields: ['Patient_Name', 'type', 'Patient_Status']
}
}).then(function(result) {
db.find({
selector: {
Patient_Name: {
$gt: true
},
type: {
$eq: 'patient'
},
Patient_Status: {
$eq: 'Active'
}
},
sort: [{
"Patient_Name": "asc"
}]
}, function(error, response) {
console.log(response);
for (i in response.docs) {
var Static_Value = Get_Static_Value();
var Last_Visit = Get_Last_Visit(response.docs[i]._id);
$('#patient_list').append('<li>' + response.docs[i]._id + ' ' + response.docs[i].Patient_Name + ' [' + Static_Value + ']' + ' ' + Last_Visit + '</li>');
}
})
});
}
Add_Patients();
Add_Visits();
$('#button_load_patients').unbind().click(function(e) {
Load_Patients();
});
function Get_Static_Value() {
return 'I am static';
}
function Get_Last_Visit(Patient_ID) {
db.createIndex({
index: {
fields: ["Visit_Date", "type"]
}
}).then(function(result) {
db.find({
selector: {
Visit_Date: {
$gt: true
},
type: {
$eq: 'visit'
},
Patient_ID: {
$eq: Patient_ID
}
},
sort: [{
"Visit_Date": "desc"
}],
limit: 1
}).then(function(response) {
console.log(response);
if (response.docs.length > 0) {
Visit_Date = response.docs[0].Visit_Date;
} else {
Visit_Date = 'Never';
}
console.log(Visit_Date);
return Visit_Date;
});
})
}
Once I have returned the "Visit_Date" value then I would manipulate it using MomentJS and include or exclude it from the results that are appended to the div.
I would appreciate any advice on what I am doing wrong.
With the help of a colleague I got the solution to this problem and will post the solution as I am sure there are people out there who are as confused as me.
The things that needed to change in my code were that the call to the "Get_Last_Visit" function needed a .then to return the value of the promise. I also needed to add "let i" to make the "i" variable a global variable and available within the function:
for (let i in response.docs) {
var Static_Value = Get_Static_Value();
Get_Last_Visit(response.docs[i]._id)
.then(function(Last_Visit) {
$('#patient_list').append('<li>' + response.docs[i]._id + ' ' + response.docs[i].Patient_Name + ' [' + Static_Value + ']' + ' ' + Last_Visit + '</li>');
})
}
Here is an updated jsfiddle.
https://jsfiddle.net/movitico/9xorLham/
I am trying to implement a way to upload files asynchronously.
I have a process I want to apply to every item of my array.
I am taking the name of each item, call a API to get additinal information about it, then I am sending it to a text to speech utility, and upload the resultingwav file to a S3 instance.
I can't find a way to do this asynchronously, and wait for all of them to finish.
I can do it in serie, but it take lots of time (12 minutes for 30 files (2mb each file)).
I tried to implement a asynchronous way, which takes around 5 minutes (7 minutes less), but I fear the problem is on the net line?
Function to apply to each item:
function doAll(c, lan, country, fileName, callback){
getNews(c, lan)
.then(function(newsResults){
getWavFile(newsResults, lan, fileName)
.then(function(wavResults){
uploadToS3(country,lan,fileName)
.then(function(s3Results){
return callback("done");
}, function(s3err){
console.log('s3 error: ',s3err);
return callback("done");
})
}, function(waverr){
console.log('wav error: ',waverr);
})
}, function(newserr){
console.log('news error: ',newserr);
})
}
Array example :
var arr = [
{
_id: '5769369ba2d42fd82ca4d851',
Name: 'Sports',
Order: 1,
Color: 'White',
Description: 'ספורט',
UpdatedDate: '2016-07-28T07:44:47.906Z',
CreatedDate: '2016-06-21T12:44:11.468Z',
Country: 'IL',
Langs: [
{
Name: 'Sports',
IsoCode: 'en',
Url: 'SportsJSON',
_id: '576b93486c7a9ff025275836'
},
{
Name: 'ספורט',
IsoCode: 'iw',
Url: 'HebrewSportsJSON',
_id: '576be6ad56126ccc25852613'
}
]
},
{
_id: '576bf4eb28176a3e5ce15afa',
Name: 'Top Stories',
Description: 'הכותרות',
Color: 'ww',
Order: 1,
UpdatedDate: '2016-07-10T12:01:26.713Z',
CreatedDate: '2016-06-23T14:40:43.435Z',
Country: 'IL',
Langs: [
{
Name: 'כותרות',
Url: 'HebrewTopStoriesJSON',
IsoCode: 'iw',
_id: '576bf52228176a3e5ce15afb'
},
{
Name: 'Top Stories',
IsoCode: 'en',
Url: 'TopStoriesJSON',
_id: '576bf94d28176a3e5ce15afd'
}
]
},
{
_id: '5756d5d6c4a3dfe478b16aa2',
Description: 'Nation Channel',
Order: 1,
Color: 'blue',
Code: 'Nation',
Name: 'Nation',
UpdatedDate: '2016-06-24T22:23:07.198Z',
CreatedDate: '2016-06-07T14:10:30.699Z',
Country: 'US',
Langs: [
{
Name: 'Nation',
IsoCode: 'en',
Url: 'NationJson',
_id: '576db2cb28176a3e5ce15b02'
}
]
}
]
My asynchronous way:
var array = [] // see the example how array look like
var newArray= [];
console.log('start uploading files time:', new Date());
for (var i = 0; i < array.length; i++) {
var list = array[i].Langs;
for (var j= 0; j < list.length; j++) {
var c = list[j];
var lan = convertIsoCode(c.IsoCode);
var fileName = array[i].Name + "_" + lan;
var country = array[i].Country;
doAll(c,lan,country,fileName, function(){
newArray.push(array[i]);
if (array.length == newArray.length) {
console.log('done');
defer.resolve('done');
}
})
}
}
EDIT:
I tried to do it with async.each and async.parallel, but didn't succeed, can anyone show me the right way to implement it?
Removed newArray since you don't need it for anything useful, it was wasting CPU time and was a horrendous way of tracking what was done. A simple counter would have done the tricks.
Gone ES6 since it's 2016. Also added semi colon because you were using them inconstitently.
Also, doAll is not a meaningful name.
'use strict';
const async = require('async');
let array = [/*data*/];
console.log('START ' + (new Date()));
//Asynchronously iterate throught the array
async.each(array, (item, callback) => {
//item is your array[i]
async.each(item.Langs, (lang, callback) => {
//lang is your array[i].Langs[j]
let lan = convertIsoCode(item.IsoCode),
fileName = item.Name + '_' + lan,
country = item.Country;
//Apply your functions
getNews(c, lan).then((newsResults) => {
getWavFile(newsResults, lan, fileName).then((wavResults) => {
uploadToS3(country,lan,fileName).then((s3Results) => {
//Everything is OK, callback without error
callback();
}, (s3err) => {
//Raise the error
callback(s3err);
});
}, (waverr) => {
console.log('wav error: ',waverr);
//Raise the error
callback(waverr);
});
}, (newserr) => {
console.log('news error: ',newserr);
//Raise the error
callback(newserr);
});
}, (error) => {
callback(error);
});
}, (error) => {
//If a error was raised, everything pending will be aborted and the error will be displayed
if(error) {
console.log(error);
//Else, just report it did fine
} else {
console.log('OK');
}
});