Handlebars.js - Combining Templates - javascript

Each section of my code below creates a new handlebars.js template to call the "User Behance API". As you can see, each section has similar code, with a variable or two difference.
Is there a way to clean up this code, and combine these separate functions into one? Just seems like a lot of code, but then again I am new to handlebars.
// BEHANCE API INFO ---
var apiKey = 'ZLBxK9rEfHwJf9K0rmseNr2fS2gS2HJW';
var userID = 'creativemints';
var perPage = 10;
var behanceUserAPI = 'http://www.behance.net/v2/users/' + userID + '?callback=?&api_key=' + apiKey;
var behanceProjectAPI = 'http://www.behance.net/v2/users/' + userID + '/projects?callback=?&api_key=' + apiKey + '&per_page=' + perPage;
// BEHANCE - USER HEADER ---
(function () {
function setUserTemplate() {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $('#userHead').html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$('header').html(result);
}
if (sessionStorage.getItem('behanceUser')) {
setUserTemplate();
} else {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
setUserTemplate();
});
}
})();
// BEHANCE - USER ABOUT ---
(function () {
function setUserTemplate() {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $('#userAbout').html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$('.about').html(result);
}
if (sessionStorage.getItem('behanceUser')) {
setUserTemplate();
} else {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
setUserTemplate();
});
}
})();
// BEHANCE - USER FOOTER ---
(function () {
function setUserTemplate() {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $('#userFoot').html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$('footer').html(result);
}
if (sessionStorage.getItem('behanceUser')) {
setUserTemplate();
} else {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
setUserTemplate();
});
}
})();
// BEHANCE - USER COPYRIGHT ---
(function () {
function setUserTemplate() {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $('#userCopyright').html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$('#copyright').html(result);
}
if (sessionStorage.getItem('behanceUser')) {
setUserTemplate();
} else {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
setUserTemplate();
});
}
})();

Haven't tested this but you should be able to simply the code to something similar to this
// BEHANCE API INFO ---
var apiKey = 'ZLBxK9rEfHwJf9K0rmseNr2fS2gS2HJW';
var userID = 'creativemints';
var perPage = 10;
var behanceUserAPI = 'http://www.behance.net/v2/users/' + userID + '?callback=?&api_key=' + apiKey;
var behanceProjectAPI = 'http://www.behance.net/v2/users/' + userID + '/projects?callback=?&api_key=' + apiKey + '&per_page=' + perPage;
// BEHANCE - USER HEADER ---
(function () {
function setUserTemplate(templateSelector, htmlSelector) {
var userData = JSON.parse(sessionStorage.getItem('behanceUser')),
getTemplate = $(templateSelector).html(),
template = Handlebars.compile(getTemplate),
result = template(userData);
$(htmlSelector).html(result);
}
if (!sessionStorage.getItem('behanceUser')) {
$.getJSON(behanceUserAPI, function (user) {
var data = JSON.stringify(user);
sessionStorage.setItem('behanceUser', data);
});
}
setUserTemplate('#userHead','header');
setUserTemplate('#userAbout','.about');
setUserTemplate('#userFoot','footer');
setUserTemplate('#userCopyright','#copyright');
})();

Related

AMQJS0011E Invalid state not connected. AWS IoT core

I'm trying to have some sort of real-time dashboard that can subscribe to AWS IoT core topics and maybe publish too.
I have found a couple of items online, but I can't figure it out.
This is what I currently have:
function p4(){}
p4.sign = function(key, msg) {
const hash = CryptoJS.HmacSHA256(msg, key);
return hash.toString(CryptoJS.enc.Hex);
};
p4.sha256 = function(msg) {
const hash = CryptoJS.SHA256(msg);
return hash.toString(CryptoJS.enc.Hex);
};
p4.getSignatureKey = function(key, dateStamp, regionName, serviceName) {
const kDate = CryptoJS.HmacSHA256(dateStamp, 'AWS4' + key);
const kRegion = CryptoJS.HmacSHA256(regionName, kDate);
const kService = CryptoJS.HmacSHA256(serviceName, kRegion);
const kSigning = CryptoJS.HmacSHA256('aws4_request', kService);
return kSigning;
};
function getEndpoint() {
const REGION = "eu-west-1";
const IOT_ENDPOINT = "blablablabla-ats.iot.eu-west-1.amazonaws.com";
// your AWS access key ID
const KEY_ID = "My-key";
// your AWS secret access key
const SECRET_KEY = "my-access-token";
// date & time
const dt = (new Date()).toISOString().replace(/[^0-9]/g, "");
const ymd = dt.slice(0,8);
const fdt = `${ymd}T${dt.slice(8,14)}Z`
const scope = `${ymd}/${REGION}/iotdevicegateway/aws4_request`;
const ks = encodeURIComponent(`${KEY_ID}/${scope}`);
let qs = `X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=${ks}&X-Amz-Date=${fdt}&X-Amz-SignedHeaders=ho
const req = `GET\n/mqtt\n${qs}\nhost:${IOT_ENDPOINT}\n\nhost\n${p4.sha256('')}`;
qs += '&X-Amz-Signature=' + p4.sign(
p4.getSignatureKey( SECRET_KEY, ymd, REGION, 'iotdevicegateway'),
`AWS4-HMAC-SHA256\n${fdt}\n${scope}\n${p4.sha256(req)}`
);
return `wss://${IOT_ENDPOINT}/mqtt?${qs}`;
}
// gets MQTT client
function initClient() {
const clientId = Math.random().toString(36).substring(7);
const _client = new Paho.MQTT.Client(getEndpoint(), clientId);
// publish method added to simplify messaging
_client.publish = function(topic, payload) {
let payloadText = JSON.stringify(payload);
let message = new Paho.MQTT.Message(payloadText);
message.destinationName = topic;
message.qos = 0;
_client.send(message);
}
return _client;
}
function getClient(success) {
if (!success) success = ()=> console.log("connected");
const _client = initClient();
const connectOptions = {
useSSL: true,
timeout: 3,
mqttVersion: 4,
onSuccess: success
};
_client.connect(connectOptions);
return _client;
}
let client = {};
function init() {
client = getClient();
client.onMessageArrived = processMessage;
client.onConnectionLost = function(e) {
console.log(e);
}
}
function processMessage(message) {
let info = JSON.parse(message.payloadString);
const publishData = {
retailer: retailData,
order: info.order
};
client.publish("sc/delivery", publishData);
}
$(document).ready(() => {
init();
client.subscribe("sc/orders/");
});
I keep getting the same error; AMQJS0011E Invalid state not connected., but I do see in the requests pane of chrome that there is an connection or so... What am I doing wrong here?
I don't see any of the logs anyhow...

Why is the module export variable empty?

I'm new to nodejs.
Here is my .js file. I'm trying to expose audioData variable to other functions. audioData variable value is being empty outside the function. I see the value when I print inside the function. What could be wrong?
'use strict';
var asyncrequest = require('request');
var xml2js = require('xml2js');
var parseString = xml2js.parseString;
var audioData = [];
asyncrequest("http://example.com/feed", function(error, responsemeta, body) {
parseString(body, function(err, result){
var stories = result['rss']['channel'][0]['item'];
console.log("Total stories: " + stories.length);
stories.forEach(function(entry) {
var singleObj = {}
singleObj['title'] = entry['title'][0];
singleObj['value'] = entry['enclosure'][0].$.url;
audioData.push(singleObj);
});
});
console.dir(audioData);
});
module.exports = audioData;
console.log("Program ended");
You'll have to return a promise for the audioData, not the audioData itself! You can learn more about promises elsewhere. Happily there's a promisified version of request, request-promise, that you can use like so:
'use strict';
var rp = require('request-promise');
var xml2js = require('xml2js');
var parseString = xml2js.parseString;
var audioData = [];
var promiseForAudioData = rp('http://example.com/feed')
.then(body => {
parseString(body, function(err, result){
var stories = result['rss']['channel'][0]['item'];
console.log("Total stories: " + stories.length);
stories.forEach(function(entry) {
var singleObj = {}
singleObj['title'] = entry['title'][0];
singleObj['value'] = entry['enclosure'][0].$.url;
audioData.push(singleObj);
});
});
return audioData;
})
.catch(console.error.bind(console));
module.exports = promiseForAudioData;
console.log("Program ended");
If you don't want to use promises, you can either export inside the callback or export the request method itself.
asyncrequest("http://example.com/feed", function(error, responsemeta, body) {
parseString(body, function(err, result){
var stories = result['rss']['channel'][0]['item'];
console.log("Total stories: " + stories.length);
stories.forEach(function(entry) {
var singleObj = {}
singleObj['title'] = entry['title'][0];
singleObj['value'] = entry['enclosure'][0].$.url; audioData.push(singleObj);
});
module.exports = audioData;
});
});
// Or
exports.get = function (callback) {
return asyncrequest(/* ... */, callback);
}
// Other module
require("./module").get(function (audioData) {
/* Do something */
})

Node.js shortened url

I have just started learning to code about 5 days ago and what I'm struggling to achieve, is to have an rssfeed-to-twitter script that posts a shortened url instead of a full website/article feed url. I found a node.js module called TinyURL that could do that but i struggle to get it to work. Here's the full script:
var simpleTwitter = require('simple-twitter');
var fs = require('fs');
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type' : 'text/plain'});
res.end('RSS Twitter Bot\n');
}).listen(5693);
var timeInterval = 300000; // run every 30m
var timerVar = setInterval (function () {runBot()}, timeInterval);
function runBot(){
var lastCompleted = Date.parse(new Date(0));
console.log(lastCompleted);
try {
var lastcompletedData = fs.readFileSync('./lastCompleted.json', 'utf8');
var timeData = JSON.parse(lastcompletedData);
var lastCompletedFromFile = Date.parse(new Date(timeData.lastCompleted));
if ( isNaN(lastCompletedFromFile) == false ) {
lastCompleted = lastCompletedFromFile;
}
} catch (e) {
console.log(e);
}
fs.readFile('./config.json', 'utf8', function (err, data) {
if (err) console.log(err); // we'll not consider error handling for now
var configData = JSON.parse(data);
console.log(configData);
var twitter = new simpleTwitter( configData.consumerKey //consumer key from twitter api
, configData.consumerSecret //consumer secret key from twitter api
, configData.accessToken //access token from twitter api
, configData.accessTokenSecret //access token secret from twitter api
, 3600);
var dateNow = Date.parse(new Date());
var FeedParser = require('feedparser');
var request = require('request');
var req = request(configData.feedUrl);
var feedparser = new FeedParser();
req.on('error', function (error) {
console.log(error);
});
req.on('response', function (res){
var stream = this;
if (res.statusCode != 200 ) return this.emit('error', new Error('Bad status code'));
stream.pipe(feedparser);
});
feedparser.on('error', function(error) {
console.log(error);
});
feedparser.on('readable', function() {
var stream = this;
var meta = this.meta;
var item;
while (item = stream.read()) {
var itemDate = Date.parse(item.date);
//check to not publish older articles
if (itemDate > lastCompleted){
var titleLength = item.title.length;
var itemTitle = item.title;
var itemLink = item.link;
if (titleLength > 100) {
itemTitle = itemTitle.substring(0, 100);
}
twitter.post('statuses/update'
, {'status' : itemTitle + ' ' + itemLink + " " + configData.tags}
, function (error, data) {
console.dir(data);
});
console.log(itemTitle + ' ' + item.link + configData.tags);
}
}
//TO KNOW WHEN FROM TO START POSTING
var dateCompleted = new Date();
console.log('loop completed at ' + dateCompleted);
var outputData = {
lastCompleted : dateCompleted
}
var outputFilename = './lastCompleted.json';
fs.writeFile(outputFilename, JSON.stringify(outputData, null, 4), function(err) {
if(err) {
console.log(err);
} else {
console.log("JSON saved to " + outputFilename);
}
});
});
});
}
And this is the TinyURL node.js module
var TinyURL = require('tinyurl');
TinyURL.shorten('http://google.com', function(res) {
console.log(res); //Returns a tinyurl
});
Changing the 'http://google.com' string to itemLink var works just fine and prints it in the terminal as expected.
TinyURL.shorten(itemLink, function(res) {
console.log(res); //Returns a tinyurl
});
What i'm trying to achieve is:
twitter.post('statuses/update', {'status' : itemTitle + ' ' + tinyurlLink + " " + configData.tags}
How can i get the response turned into a e.g var tinyurlLink to replace the itemLink var? Any help would be much appreciated!
As suggested by #zerkms sending a tweet from inside the TinyURL.shorten worked!

aws lambda function how to use responses to perform calculation

Trying to create a lambda function that lists tagged ec2 and tagged rds and performs an action thereafter. This is the first time i have used javascript and would appreciate some help.
Please see my example below
var aws = require('aws-sdk');
var ec2 = new aws.EC2();
var rds = new aws.RDS();
aws.config.region = 'us-east-1';
exports.handler = function(event,context) {
if (event) {
console.log(event.id);
}
//setup params for rds call
var rdsparams = {
DBInstanceIdentifier: 'master',
};
//setup params for ec2 call
var ec2params = {
Filters: [
{
Name: 'tag:role',
Values: [
'app'
],
}
]
};
//Get ec2 instances with app tag, may need to add a condition on running so pulled it into hash
ec2.describeInstances(ec2params, function(err, appdata) {
if (err) {
console.log(err);
return;
}
else {
var apparray={};
for(var i = 0; i < appdata.Reservations.length; i++) {
var ins = appdata.Reservations[i].Instances[0];
var id = ins.InstanceId;
var state = ins.State.Name;
apparray[id]=state;
}
console.log(apparray);
context.succeed(apparray);
}
});
rds.describeDBInstances(rdsparams, function(err, data) {
if (err) {
console.log(err, err.stack);
return;
}
else {
var rdsarray={};
var rdsarray=(data);
console.log(rdsarray);
var ins=rdsarray[0];
var name = ins.ReadReplicaDBInstanceIdentifiers[0];
rdsarray[replicant]=name;
}
context.succeed(rdsarray);
});
//context.done();
};
I want to return my filtered (apparray) and (rdsarray) back from my functions and perform a calculation on this within the main body of the script. Any ideas on how to do this.
something like
var replicas = rdsarray.length for example
Thanks in advance
var aws = require('aws-sdk');
var ec2 = new aws.EC2();
var rds = new aws.RDS();
aws.config.region = 'us-east-1';
exports.handler = function(event, context) {
if (event) {
console.log(event.id);
}
//setup params for rds call
var rdsparams = {
DBInstanceIdentifier: 'master',
};
//setup params for ec2 call
var ec2params = {
Filters: [{
Name: 'tag:role',
Values: [
'app'
],
}]
};
//Get ec2 instances with app tag, may need to add a condition on running so pulled it into hash
ec2.describeInstances(ec2params, function(err, appdata) {
if (err)
return context.done(err, null);
var apparray = {};
for (var i = 0; i < appdata.Reservations.length; i++) {
var ins = appdata.Reservations[i].Instances[0];
var id = ins.InstanceId;
var state = ins.State.Name;
apparray[id] = state;
}
console.log(apparray);
var resultData = {};
resultData.apparray = apparray;
rds.describeDBInstances(rdsparams, function(err, data) {
if (err)
return context.done(err, null);
var rdsarray = {};
var rdsarray = (data);
console.log(rdsarray);
var ins = rdsarray[0];
var name = ins.ReadReplicaDBInstanceIdentifiers[0];
rdsarray[replicant] = name;
resultData.rdsarray = rdsarray;
context.done(null, resultData);
});
});
};
and back in the code from you are calling the lambda function
var lambda = new sdk.Lambda();
var params = {
FunctionName: 'arn:aws:lambda:us-west-2:1541546477777:function:MyFunction',
Payload: JSON.stringify(/*your params here*/)
};
lambda.invoke(params, function(err, data) {
if (err) {
console.log('error ===', err);
return ;
}
var lambdaData = JSON.parse(data.Payload);
// do your stuff here
});
Is this what you needed? It may be broken but I hope you get the idea of it

Node.js callback confusion

I am trying to implement an autocompleter on a nodejs app using nowjs.
everyone.now.sendAutocomplete = function(search) {
var response = getAutocomplete(search);
console.log("response");
console.log(response);
};
which calls:
function getAutocomplete(search) {
console.log(search);
var artist = new Array();
request({uri: 'http://musicbrainz.org/ws/2/artist/?query=' + search + '&limit=4', headers: "Musicbrainz Application Version 1"}, function(error, response, body) {
par.parseString(body, function(err, result) {
var count = result['artist-list']['#']['count'];
var artists = result['artist-list']['artist'];
// var artist = new Array();
if (count > 1) {
artists.forEach(function(a) {
var att = a['#'];
var id = att['id'];
var name = a['name'];
var dis = a['disambiguation'];
if (dis) {
var display = name + " (" + dis + " )";
} else {
display = name;
}
artist.push({'id':id, 'name': name, 'disambiguation':dis,
'label':display, 'value':name, 'category':"Artists"});
});
//everyone.now.receiveResponse(artist);
console.log("artist");
console.log(artist);
return artist;
} else {
console.log(artists);
var att = artists['#'];
var id = att['id'];
var name = artists['name'];
var dis = artists['disambiguation'];
var resp = [{'id':id, 'name': name, 'disambiguation':dis,
'label':name, 'value':name, 'category':"Artists"}];
return resp;
// everyone.now.receiveResponse([{'id':id, 'name': name, 'disambiguation':dis,
// 'label':name, 'value':name, 'category':"Artists"}]);
}
});
});
}
However, console.log(response) says that response is undefined. I am new to node so the answer is probably simple, but still can't figure it out.
You are treating the async call as synchronous. Your getAutocomplete needs to take a callback function to get the response. You're using that a lot already, in your request call and your parseString call.
Like this:
everyone.now.sendAutocomplete = function(search) {
getAutocomplete(search, function (response) {
console.log("response");
console.log(response);
});
};
And instead of return:
function getAutocomplete(search, callback) {
// ...
callback(result);
// ...
}

Categories