Javascript array grouped in 3's - javascript

I'm trying to parse rss feed.
But what I want to get is:
1) an array grouped in 3 elements. So I have different feed with only its own data grouped together - so it becomes easy to call.
Example :
myArr = [{title, date, content}, {title,date,content}, ....... ]
2) How do I access this array and its elements from outside this function?
I used console.log just to show you guys an idea of what I'm trying to achieve here.
Thanks guys for helping!!
var parser = require('rss-parser');
function myFunc(){
parser.parseURL('https://www.reddit.com/.rss', function(err, parsed) {
console.log(parsed.feed.title);
parsed.feed.entries.forEach(function(entry) {
var items = [];
items.push(entry.title, entry.pubDate, entry.content.split('src=')[1]);
console.log("Title: " + items[0])
console.log("Date: " + items[1])
console.log("Content: " + items[2]);
console.log(" +++++++++++++++ ")
});
});
};
myFunc();
========
OutPut I get :
+++++++++++++++
Title: Brave Floridian workers delivering pizza during hurricane Irma.
Date: 2017-09-10T23:57:01.000Z
Content: "https://b.thumbs.redditmedia.com/4B5QcikKMP8fU90wk6cpR99LSkppsvBIbo88j
4YgysY.jpg" alt="Brave Floridian workers delivering pizza during hurricane Irma.
" title="Brave Floridian workers delivering pizza during hurricane Irma." /> </a
> </td><td> submitted by <a href="https://www.reddit.com/user/Daului
gi51"> /u/Dauluigi51 </a> to <a href="https://www.reddit.com/r/Bikin
iBottomTwitter/"> r/BikiniBottomTwitter </a> <br/> <span><a href="https://i.redd
.it/wuu9mews85lz.jpg">[link]</a></span> <span><a href="https://www.reddit.
com/r/BikiniBottomTwitter/comments/6zbunz/brave_floridian_workers_delivering_piz
za_during/">[comments]</a></span> </td></tr></table>
+++++++++++++++
Title: Redditor Provides Specific, Clear Instructions to Aid a User in Helping P
eople Hit By Hurricane Irma in the U.S. Virgin Islands
Date: 2017-09-11T04:30:26.000Z
Content: undefined
+++++++++++++++
Title: A fellow Florida 501st member posted this on his Facebook
Date: 2017-09-11T00:04:25.000Z
Content: "https://b.thumbs.redditmedia.com/C1Putt8Dihjv31fxqqpwOD3NHMbEddkMUogsW
j4DHLA.jpg" alt="A fellow Florida 501st member posted this on his Facebook" titl
e="A fellow Florida 501st member posted this on his Facebook" /> </a> </td><td>
submitted by <a href="https://www.reddit.com/user/morgul702"> /u/mor
gul702 </a> to <a href="https://www.reddit.com/r/StarWars/"> r/StarW
ars </a> <br/> <span>[link]</span>
<span><a href="https://www.reddit.com/r/StarWars/comments/6zbvyq/a_fellow
_florida_501st_member_posted_this_on_his/">[comments]</a></span> </td></tr></tab
le>
+++++++++++++++

If I understood you well
const items = parsed.feed.entries.map((entry) => ({
title: entry.title,
date: entry.pubDate,
content: entry.content.split('src=')[1],
}));
You are gonna get something like items = [{title, date, content}, {title,date,content}, ....... ]

Promises allow you to access the results of an async function from outside of the callback. I believe this is what you are looking for:
var parser = require('rss-parser');
function myFunc() {
return new Promise((resolve) => { // Promise to allow async access outside of the function
parser.parseURL('https://www.reddit.com/.rss', (err, parsed) => {
resolve(parsed.feed.entries.map(entry => ({ title: entry.title, date: entry.pubDate, content: entry.content.split('src=')[1] }))); // Mapping into objects of title, date and entry
});
});
};
myFunc().then((entries) => {
console.log(entries[0].title); // Output the title of the first result
console.log(entries);
});

Related

Better, cleaner way of writing this code?

I am fairly new to coding and wanted a better (less repetative) way of creating this line of code for my fetch call. I'll add the important parts of the code.
HTML
<form id= 'selectionForm' action="#">
<p>
<label>
<input type="checkbox" class="filled-in" name="Nexflix" id="Nexflix"/>
<span>Netflix</span>
</label>
</p>
</form>
Javascript
document.getElementById('fetch').addEventListener('click', function (element) {
element.preventDefault();
let checkedElements = document.querySelectorAll('#Nexflix:checked');
var options = {
method: "GET",
headers: {
"X-RapidAPI-Key": "using my own",
"X-RapidAPI-Host": "streaming-availability.p.rapidapi.com",
},
};
let outputContainer = document.getElementById('output');
for (let e of checkedElements) {
fetch('https://streaming-availability.p.rapidapi.com/search/basic?country=us&service=netflix&service=netflix&type=movie&genre=18&page=1&output_language=en&language=en', options).then((response) => response.json()).then( (data) => {
outputContainer.appendChild(document.createTextNode('The checked element is : '+e.id));
outputContainer.appendChild(document.createElement("br"));
outputContainer.appendChild(document.createTextNode(data.results[0].title));
outputContainer.appendChild(document.createElement("br"));
outputContainer.appendChild(document.createTextNode('IMDB Rating : ' + data.results[0].imdbRating));
outputContainer.appendChild(document.createElement("br"));
outputContainer.appendChild(document.createTextNode('Year of release : ' + data.results[0].year));
outputContainer.appendChild(document.createElement("br"));
outputContainer.appendChild(document.createTextNode('Overview : ' + data.results[0].overview));
outputContainer.appendChild(document.createElement("br"));
outputContainer.appendChild(document.createTextNode(data.results[1].title));
I would also like to repeat this for other films/results from the API. They give results like
{2 items
"results":[8 items
0:{21 items
"age":10
"backdropPath":"/pYziM5SEmptPW0LdNhWvjzR2zD1.jpg"
"backdropURLs":{...}4 items
"cast":[...]4 items
"countries":[...]1 item
"genres":[...]2 items
"imdbID":"tt9850370"
"imdbRating":64
"imdbVoteCount":1069
"originalTitle":"#AnneFrank. Parallel Stories"
"overview":"One single Anne Frank moves us more than the countless others who suffered just as she did but whose faces have remained in the shadows-Primo Levi. The Oscar®-winning Helen Mirren will introduce audiences to Anne Frank's story through the words in her diary. The set will be her room in the secret refuge in Amsterdam, reconstructed in every detail by set designers from the Piccolo Theatre in Milan. Anne Frank this year would have been 90 years old. Anne's story is intertwined with that of five Holocaust survivors, teenage girls just like her, with the same ideals, the same desire to live: Arianna Szörenyi, Sarah Lichtsztejn-Montard, Helga Weiss and sisters Andra and Tatiana Bucci. Their testimonies alternate with those of their children and grandchildren."
"posterPath":"/hkC4yNDFmW1yQuQhtZydMeRuaAb.jpg"
"posterURLs":{...}7 items
"runtime":92
"significants":[...]2 items
"streamingInfo":{...}1 item
"tagline":""
"title":"#AnneFrank. Parallel Stories"
"tmdbID":"610643"
"video":"FzT7-NfkxLA"
"year":2019
}
1:{...}21 items
2:{...}21 items
3:{...}21 items
4:{...}21 items
5:{...}21 items
6:{...}21 items
7:{...}21 items
Thank you for your time reading this!
Use <p>aragraphs instead of text nodes with many linebreaks inbetween.
You can create them easily in a loop:
const lines = [
'The checked element is : '+e.id,
data.results[0].title,
'IMDB Rating : ' + data.results[0].imdbRating,
'Year of release : ' + data.results[0].year,
'Overview : ' + data.results[0].overview,
data.results[1].title
];
for (const line of lines) {
const paragraph = document.createElement('p');
paragraph.appendChild(document.createTextNode(line));
outputContainer.appendChild(paragraph);
}

How to fully create HTML from a js object?

I am working on finding a way to use javascript to create blog posts for my website. I am quite knowledgeable in javascript, however I haven't used many DOM elements other than document.getElementById(). I am looking for support in how to implement a way to turn a JS object into a post. Here is an example object:
var posts = { //My object
firstPost: { //An example post
index: 1, //Identifies order of posts: 1 is oldest... >1 newest
id: "first", //An id for the post
date: { //Date will be listed next to name on post
month: 11,
day: 2,
year: 2018
},
name: "My Post", //Name of the post
text: "Text for the post...", //Actual Post
image: 'blogImage.png' //An image for the post
}
And now I want to pass it through a function as shown below to create HTML:
function assemblePost( index, id, month, day, year, text, image) {
//DOM GOES IN HERE
}
Here is an example of how the HTML looks when I type it manually:
<div class="card" id="first"> <!-- Card element links to css -->
<h2>My Post</h2> <!-- Name of the post -->
<h5>Posted November 2nd, 2018</h5> <!-- Date of the post -->
<div class="img" style="height:200px;"><img src="/blogImage.png" ></div>
<p>Text for the post..."</p> <!-- Actual Post -->
</div>
I am not entirely sure how to approach this because:
The class, "card", links to the CSS, and I am not sure how to implement that with DOM.
I am not sure if DOM can edit style, as in this example, the image height is 200, but in another image it could be different.
For many of my other posts, I may have multiple paragraphs and/or lists. At the very least, I wanted a way to create one string of text. Maybe for lists, an array would be most useful in my object, however I am unsure how to address multiple paragraphs.
I realize it is a lot of explaining, examples, and guidelines, but I really do appreciate your help! Thank you!
Just do it step by step.
var posts = [ //My object (array of posts)
{ //An example post
index: 1, //Identifies order of posts: 1 is oldest... >1 newest
id: "first", //An id for the post
date: { //Date will be listed next to name on post
month: 11,
day: 2,
year: 2018
},
name: "My Post", //Name of the post
text: "Text for the post...", //Actual Post
image: 'blogImage.png' //An image for the post
},
{ //An example post
index: 2, //Identifies order of posts: 1 is oldest... >1 newest
id: "first", //An id for the post
date: { //Date will be listed next to name on post
month: 11,
day: 2,
year: 2018
},
name: "My another Post", //Name of the post
text: "Text for another post...", //Actual Post
image: 'blogImage.png' //An image for the post
}
];
const container = document.getElementById('div-posts');
posts.forEach(function(post) {
let div = document.createElement('div');
div.className = 'card';
div.id = 'post_' + post.index; //or post.id provided itis unique
//create more elements instead of ".innerHTML" if you wish
div.innerHTML = '<h2>' + post.name + '</h2>' +
'<h5>' + (new Date(post.date.year, post.date.month, post.date.day).toDateString()) + '</h5>' +
'<div class="img"><img src="/' + post.image + '" ></div>' +
'<p>' + post.text + '</p>';
container.appendChild(div);
});
.card {
border: solid 1px #ccc;
width: 400px
}
.img img {
max-width: 100%
}
<div id="div-posts"></div>

AngularJS, ng-repeat doesn't repeat

I'm new in AngularJs and I'm facing a problem with ng-repeat. Basically, I want to get the comments relative to an article from my database with ajax, then to display them with ng-repeat. I then have an array in which I push my comments. My problem is that when I manually create a comment in my array, it works well, but if I push automatically this comment from the callback of my ajax function, the array is updated, but not my view.
View in html :
var articleApp = angular.module('articleApp', []);
articleApp.controller('CommentsController', function CommentsController($scope) {
$scope.comments = [];
// This push works well, my view is updated
$scope.comments.push({
content: "Hello world !",
date: "2 minutes ago",
id: 29,
author: {
pseudo: "Sean"
}
});
// When I push with this function, my array is updated, but not the view
$scope.addComment = function(comment) {
$scope.comments.push({
content: comment.comment,
id: comment.id,
date: comment.date_post,
author: {
id: comment.author.id,
pseudo: comment.author.pseudo
}
});
};
var articleID = document.getElementById('articleID').textContent;
// getComments is defined elsewhere, and returns the 20 first comments
getComments(20, articleID, 0, function(comments) {
for(var i = 0; i < comments.length; i++) {
$scope.addComment(comments[i]);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<section id="commentsSection" class="bottom_apps" ng-controller="CommentsController as comments">
<article id = "{{comment.id}}" class="comment_container" ng-repeat="comment in comments">
<div class="comment_header">
<span class="comment_author">{{comment.author.pseudo}}</span>
<span class="comment_date">{{comment.date}}</span>
</div>
<div class="comment_content">
{{comment.content}}
</div>
</article>
</section>
I double-checked, triple-checked all my code, but I can't see where I did a mistake.
Looks like your getComments works asynchronously, since you are passing a callback function which has the comments as a parameter.
Therefore, even though you update your comments inside that callback, AngularJS does not seem to "notice it", right?
This is because you have to tell AngularJS explicitly to run a new digest cycle.
In short, just add $scope.$apply() to the end of your callback:
getComments(20, articleID, 0, function(comments) {
for(var i = 0; i < comments.length; i++) {
$scope.addComment(comments[i]);
}
$scope.$apply();
});
To learn more about this, search for "AngularJS digest cycle". In short, the thing is: AngularJS updates everything in what are called digest cycles. If a digest cycle does not happen, AngularJS will not "notice" the changes. When things runs synchronously, AngularJS automatically runs digest cycles. But for many asynchronous things, AngularJS can't figure it out automatically, so you have to tell AngularJS explicitly to perform a digest cycle.
You can try doing something like below code, Also please check this plunker link for your given example scenario with some dummy action.
Controller:
$scope.comments = [];
$scope.comment={};
// This push works well, my view is updated
$scope.comments.push({
content: "Hello world !",
date: "2 minutes ago",
id: 29,
author: {
pseudo: "Sean"
}
});
$scope.comments.push({
content: "Hello world 2!",
date: "5 minutes ago",
id: 30,
author: {
pseudo: "Jack"
}
});
// When I push with this function, my array is updated, but not the view
$scope.addComment = function() {
$scope.comments.push({
content: $scope.comment.comment,
id: $scope.comments.length+1,
date: new Date(),
author: {
id: $scope.comments.length+1,
pseudo: $scope.comment.comment
}
});
console.log($scope.comments);
};
Template:
<section id="commentsSection" class="bottom_apps" ng-controller="CommentsController">
<input type="text" ng-model="comment.comment"/>
<button type="button" ng-click="addComment()">Add Comment</button><br/>
<article id = "{{comment.id}}" class="comment_container" ng-repeat="comment in comments">
<div class="comment_header">
<span class="comment_author">{{comment.author.pseudo}}</span>
<span class="comment_date">{{comment.date}}</span>
</div>
<div class="comment_content">
{{comment.content}}
</div>
</article>
</section>

search to json pull from API to html all nice and pretty?

I'm working on a project for a client where the site visitors can search Campusbooks.com and get the results displayed.
Contacted Campusbooks and was told that I can use their API and have fun... and that's it.
I've found how to create a search form that pulls the results as posts the raw JSON. There's no formatting in the JSON so what I am getting is
"response":{
"#attributes":{
"status":"ok",
"version":"10"
},
"label":{
"#attributes":{
"plid":"3948",
"name":"Textbooks 4 You"
}
},
"page":{
"#attributes":{
"name":"search"
},
"count":"1000",
"pages":"100",
"current_page":"1",
"results":{
"book":[{
"isbn10":"1463590776",
"isbn13":"9781463590772",
"title":"Life on the Mississippi",
"author":"Mark Twain",
"binding":"Paperback",
"msrp":"13.99",
"pages":"316",
"publisher":"CreateSpace",
"published_date":"2011-06-19",
"edition":"Paperback",
"rank":"99999999",
"rating":"0.0",
"image":"http://ecx.images-amazon.com/images/I/51sXKpUcB0L.SL75.jpg"
},
{
"isbn10":"1406571253",
"isbn13":"9781406571257",
"title":"How to Tell a Story and Other Essays (Dodo Press)",
"author":"Mark Twain",
"binding":"Paperback",
"msrp":"12.99",
"pages":"48",
"publisher":"Dodo Press",
"published_date":"2008-02-29",
"edition":"Paperback",
"rank":"214431",
"rating":"0.0",
"image":"http://ecx.images-amazon.com/images/I/41S5poITLpL.SL75.jpg"
},
{
"isbn10":"0520267192",
"isbn13":"9780520267190",
"title":"Autobiography of Mark Twain, Vol. 1",
"author":"Mark Twain",
"binding":"Hardcover",
"msrp":"34.95",
"pages":"743",
"publisher":"University of California Press",
"published_date":"2010-11-15",
"edition":"1",
"rank":"344",
"rating":"0.0",
"image":"http://ecx.images-amazon.com/images/I/41LndGG6ArL.SL75.jpg"
},
{
"isbn10":"1936594595",
"isbn13":"9781936594597",
"title":"The Adventures of Huckleberry Finn",
"author":"Mark Twain",
"binding":"Paperback",
"msrp":"8.88",
"pages":"270",
"publisher":"Tribeca Books",
"published_date":"2011-04-07",
"edition":"Paperback",
"rank":"1285",
"rating":"0.0",
"image":"http://ecx.images-amazon.com/images/I/51J4kzmKcpL.SL75.jpg"
}
]
}
}
}
}
I need to take that output and make it all nice and pretty in HTML.
The script I am using to do this with at this point is:
// Vanilla JS Example: CampusBooksJS
(function () {
var CampusBooks = require('campusbooks'),
// This key is a special dummy key from CampusBooks for public testing purposes
// Note that it only works with Half.com, not the other 20 textbook sites, so it's not very useful,
// but good enough for this demo
cb = CampusBooks.create("T4y4JKewp48J2C72mbJQ"),
cbform = document.getElementById("vanilla-campusbooksjs-form");
// Note: This is for demonstration purposes only (with modern browsers)
// Use MooTools or jQuery for a real-world solution that works cross-browser
// (and please don't write you own, it's not worth it)
function cbSearch(e) {
var cbform = this,
search = cbform.querySelector("select").value,
data = cbform.querySelector("input").value;
e.preventDefault();
if (!data) {
alert("Try Typing in a Keyword or Two First");
return;
}
alert("Your Search: " + search + ": " + JSON.stringify(data, null, ' '));
var params = {};
params[search] = data;
cb.search(params).when(function (err, nativeHttpClient, data) {
if (err || !data) {
alert("Error: " + JSON.stringify(err) || "No Data Returned");
return;
}
document.querySelectorAll("#vanilla-campusbooksjs-display")[0].innerHTML = JSON.stringify(data, null, ' ');
});
}
// This will work on modern browsers only
cbform.addEventListener("submit", cbSearch, false);
}());
The search form is:
<form id="vanilla-campusbooksjs-form">
<select name="cb_search">
<option>keywords</option>
<option>author</option>
<option>isbn</option>
</select>
: <input name="cb_value" type="text"/>
<input type="submit" value="Search"/>
</form>
<div>
<pre>
<code id="vanilla-campusbooksjs-display">
</code>
</pre>
</div>
I hope this isn't too long of a post. If additional information is needed, please let me know.
I would suggest using Mustache Templates. Its easy to apply mustache templates to JSON and get some markup. It can be done on the server or client side.

How to insert variables into text when storing content in an object?

I'm using the code below to insert content into a page. I need to insert some variables in the text to generate some dynamic values and am unsure how to do this. Can someone tell me what I'd need to change?
Here's a slimmed down example of how I'm storing the data in my JS:
var fruit = {
'apples': {
'goldenDelicious' : {
color: 'yellow',
sale: 'A sale of $XXXXX (need to insert a number in here). Be sure to buy some before they are all gone!',
link: {
linkText: ('This company sells this for $XXXXX (eed to insert a price here). Click here to visit their site.'),
url: 'I NEED TO INSERT THE URL HERE'
}
}
}
}
Here's an example of how I'm calling it: (it's more dynamic than this, but you get the idea)
var fruitType = 'apples';
var fruitVariety = 'goldenDelicious';
fruit[fruitType][fruitVariety], function () {
// do something
});
So what I'd like is to be able to insert values like a price, sale, and URL into the object.
There are a bunch of ways to do this. If you're going to be doing a lot of this type of replacement, you'll probably want to look at a templating engine. I've been using Trimpath, and am happy with it.
If you don't want to get that fancy yet, put your own placeholder tokens in the string and then replace them.
var fruit = {
'apples': {
'goldenDelicious' : {
color: 'yellow',
sale: 'A sale of PLACEHOLDER_1. Be sure to buy some before they are all gone!',
link: {
linkText: ('This company sells this for PLACEHOLDER_2. Click here to visit their site.'),
url: 'I NEED TO INSERT THE URL HERE'
}
}
}
}
fruit.apples.goldenDelicious.sale = fruit.apples.goldenDelicious.sale.replace("PLACEHOLDER_1", "the real value");

Categories