How to use .each to build an array - javascript

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)
})

Related

Calling Values from Functions with PouchDB using Find() within a loop

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/

node js - multi tasking for each item in array

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');
}
});

Insert dynamic listbox options in Tinymce popup editor

I am trying to create dynamic listbox values but getting this error in console:
Uncaught TypeError: Cannot assign to read only property 'active' of [
Here's my code( pasting only the code for listbox ):
body: [
{
type: 'listbox',
name: 'type',
label: 'Panel Type',
value: type,
'values': get_author_list(),
tooltip: 'Select the type of panel you want'
},
]
.....
And I am calling this function to get dynamic list...
function get_author_list() {
var d = "[{text: 'Default', value: 'default'}]";
return d;
}
I am guessing that the values in listbox only takes static var and not dynamic. But I need to insert dynamic values in this list. Please can anyone help me find a workaround. Is there any possibility to insert via ajax?
Thanks, in advance!!
I needed something similar for .NET site. Even though is not great code I hope it can help someone.
tinymce.PluginManager.add('DocumentSelector', function (editor, url) {
// Add a button that opens a window
editor.addButton('DocumentSelector', {
text: 'Document',
icon: false,
title: "Document Selector",
onclick: function () {
var _documentList;
//load all documents
var _data = JSON.stringify({/* Some data */});
$.ajax({
type: "POST",
url: "/api/TinyMCE/GetDocuments",
data: _data,
contentType: "application/json; charset=utf-8",
dataType: "json",
processData: true,
success: function (data) {
_documentList = eval('(' + data + ')');
// Open window
editor.windowManager.open({
title: 'Document Selector',
body: [
{
type: 'listbox',
name: 'DocURL',
label: 'Documents',
values: _documentList
},
{
type: 'textbox'
, name: 'TextToDisplay'
, value: _text
, label: 'Text To Display'
},
{
type: 'textbox'
, name: 'TitleToDisplay'
, value: _title
, label: 'Title'
},
{
type: 'listbox',
name: 'TheTarget',
label: 'Target',
values: [{ text: 'None', value: "_self" }, { text: 'New Window', value: "_blank" }],
value: _target
}
],
onsubmit: function (e) {
// Insert content when the window form is submitted
}
});
},
error: function (xhr, status, error) {
alert("Error! " + xhr.status + "\n" + error);
}
});
}
});
});
And here it is some of the Behind code
public class TinyMCEController : ApiController
{
public class DocumentsInfo
{
// Some data
}
public class DocumentList
{
public string text { get; set; }
public string value { get; set; }
}
[HttpPost]
[ActionName("GetDocuments")]
public object GetDocuments(DocumentsInfo docInfo)
{
//Test data
List<DocumentList> _DocumentList = new List<DocumentList>();
_DocumentList.Add(new DocumentList {
text = "Document1.pdf",
value = "value1"
});
_DocumentList.Add(new DocumentList
{
text = "Document2.pdf",
value = "value2"
});
var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(_DocumentList);
return json;
}
}

ckeditor plugin dialog select get the description from the selected one

Im am developing a placeholder plugin to CKEDITOR and it´s basically complete. The problem I have is that I am trying to get the value and description from the select within the dialog and I am only getting the value.
The array that contains the description and value looks like this
-->
items: [['description1', 'value1'], ['description2', 'value2']] <--
In the return -> contents -> elements with ID dropdown I have setup and commit function. In these functions I need to get the description just like getting the name from select option.
Really need help with this one, thanks in advance
example -->
<select>
<option value="value1">description1</option>
<option value="value2">description2</option>
</select>
example <--
(function () {
function placeholderDialog(editor, isEdit) {
var lang = editor.lang.phlink,
generalLabel = editor.lang.common.generalTab;
return {
title: lang.title,
minWidth: 300,
minHeight: 80,
contents: [
{
id: 'info',
label: generalLabel,
title: generalLabel,
elements: [
{
id: 'dropdown'
, type: 'select'
, label: lang.chooseVal
, 'default': 'Detta är default'
, items: [['description1', 'value1'], ['description2', 'value2']]
, setup: function (data) {
// need the description
this.setValue(data.title);
}
, commit: function (data) {
// need the description
data.title = this.getValue();
}
},
{
id: 'text',
type: 'text',
style: 'width: 100%;',
label: lang.text,
'default': '',
required: true,
validate: CKEDITOR.dialog.validate.notEmpty(lang.textMissing),
setup: function (data) {
this.setValue(data.text);
},
commit: function (data) {
data.text = this.getValue();
}
}
]
}
],
onShow: function () {
var data = { tag: 'link', content: "detta är innehåll", title: "Länk till svar", text: "detta är text" };
if (isEdit) {
this._element = CKEDITOR.plugins.phlink.getSelectedPlaceHolder(editor);
data.title = this._element.getAttribute('title');
data.text = this._element.getText();
data.tag = this._element.getAttribute('data-jztag');
}
this.setupContent(data);
},
onOk: function () {
var data = { tag: 'link', content: null, title: null, text: null };
this.commitContent(data);
CKEDITOR.plugins.phlink.createPlaceholder(editor, this._element, data);
delete this._element;
}
};
}
CKEDITOR.dialog.add('createplaceholder', function (editor) {
return placeholderDialog(editor);
});
CKEDITOR.dialog.add('editplaceholder', function (editor) {
return placeholderDialog(editor, 1);
});
})();
Use the following to get option's text:
var input = this.getInputElement().$;
console.log( input.options[ input.selectedIndex ].text );
>> "description1"

JQuery get data from JSON array

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);
});
});

Categories