Use NPM to download a free module called “ moment ” described in our textbook an
ID: 3873830 • Letter: U
Question
Use NPM to download a free module called “moment” described in our textbook and use Node.js built-in “fs” module to log the customer feedback messages to a text file named “feedback.log”. Each feedback has to be logged on its own line and has to be started with a time stamp in a pair of square brackets.
app.js
/**
app.js
This is a simple web site that hosts
a fake Wake Tech Credit Union web site.
It is used to demonstrate how easy it is to
create and deploy a web sever using Node.js.
*/
var moment = require('./node_modules/moment');
var express = require('express');
var fs = require('fs');
/**
* Define the sample application.
*/
var SampleApp = function() {
// Scope.
var self = this;
/* ================================================================ */
/* Helper functions. */
/* ================================================================ */
/**
* Set up server IP address and port # using env variables/defaults.
*/
self.setupVariables = function() {
// Set the environment variables we need.
//self.ipaddress = process.env.IP;
//self.port = process.env.PORT || 5000;
//if (typeof self.ipaddress === "undefined") {
// self.ipaddress = "127.0.0.1";
//};
};
/**
* Populate the cache.
*/
self.populateCache = function() {
if (typeof self.zcache === "undefined") {
self.zcache = { 'index.html': '' };
}
// Local cache for static content.
self.zcache['index.html'] = fs.readFileSync('./index.html');
};
/**
* Retrieve entry (content) from cache.
* @param {string} key Key identifying content to retrieve from cache.
*/
self.cache_get = function(key) { return self.zcache[key]; };
/**
* terminator === the termination handler
* Terminate server on receipt of the specified signal.
* @param {string} sig Signal to terminate on.
*/
self.terminator = function(sig){
if (typeof sig === "string") {
console.log('%s: Received %s - terminating sample app ...',
Date(Date.now()), sig);
process.exit(1);
}
console.log('%s: Node server stopped.', Date(Date.now()) );
};
/**
* Setup termination handlers (for exit and a list of signals).
*/
self.setupTerminationHandlers = function(){
// Process on exit and signals.
process.on('exit', function() { self.terminator(); });
// Removed 'SIGPIPE' from the list - bugz 852598.
['SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', 'SIGTRAP', 'SIGABRT',
'SIGBUS', 'SIGFPE', 'SIGUSR1', 'SIGSEGV', 'SIGUSR2', 'SIGTERM'
].forEach(function(element, index, array) {
process.on(element, function() { self.terminator(element); });
});
};
/* ================================================================ */
/* App server functions (main app logic here). */
/* ================================================================ */
/**
* Create the routing table entries + handlers for the application.
*/
self.createRoutes = function() {
self.routes = { };
self.routes['/feedback'] = function(req, res) {
console.log("-- Received a customer feedback: [" + req.body.feedback + "]");
res.send("<html><head><title>WTCU Feedback</title><script>setTimeout(function(){window.location.href='/'},3000);</script></head><body>Thanks for your feedback!</body></html>");
};
self.routes['/'] = function(req, res) {
res.setHeader('Content-Type', 'text/html');
res.send(self.cache_get('index.html') );
};
};
/**
* Initialize the server (express) and create the routes and register
* the handlers.
*/
self.initializeServer = function() {
self.createRoutes();
//self.app = express.createServer();
self.app = express();
self.app.set('port', process.env.PORT || 3333);
self.app.set('ip', process.env.IP || "127.0.0.1");
self.app.use(express.static(__dirname));
//self.app.use(express.bodyParser());
self.app.use(express.json());
self.app.use(express.urlencoded());
// Add handlers for the app (from the routes).
for (var r in self.routes) {
self.app.get(r, self.routes[r]); // maps the HTTP GET request
self.app.post(r, self.routes[r]); // maps the HTTP POST request
}
};
/**
* Initializes the sample application.
*/
self.initialize = function() {
self.setupVariables();
self.populateCache();
self.setupTerminationHandlers();
// Create the express server and routes.
self.initializeServer();
};
/**
* Start the server (starts up the sample application).
*/
self.start = function() {
// Start the app on the specific interface (and port).
self.app.listen(self.app.get('port'), function() {
console.log('%s: Node server started on %s:%d ...',
Date(Date.now() ), self.app.get('ip'), self.app.get('port'));
});
};
}; /* Sample Application. */
/**
* main(): Main code.
*/
var zapp = new SampleApp();
zapp.initialize();
zapp.start();
feedback.js
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Wake Tech Credit Union</title>
<link rel="stylesheet" type="text/css" href="css/interface.css" />
<style>
* {
font-family: Verdana, Arial, sans-serif;
}
a:link {
color:#000;
text-decoration: none;
}
a:visited {
color:#000;
}
a:hover {
color:#33F;
}
.button {
background: -webkit-linear-gradient(top,#008dfd 0,#0370ea 100%);
border: 1px solid #076bd2;
border-radius: 3px;
color: #fff;
display: none;
font-size: 13px;
font-weight: bold;
line-height: 1.3;
padding: 8px 25px;
text-align: center;
text-shadow: 1px 1px 1px #076bd2;
letter-spacing: normal;
}
.center {
padding: 10px;
text-align: center;
}
.final {
color: black;
padding-right: 3px;
}
.interim {
color: gray;
}
.info {
font-size: 14px;
text-align: center;
color: #777;
display: none;
}
.right {
float: right;
}
.sidebyside {
display: inline-block;
width: 45%;
min-height: 40px;
text-align: left;
vertical-align: top;
}
#headline {
font-size: 40px;
font-weight: 300;
}
#info {
font-size: 20px;
text-align: center;
color: #777;
visibility: hidden;
}
#results {
font-size: 14px;
font-weight: bold;
border: 1px solid #ddd;
padding: 15px;
text-align: left;
min-height: 150px;
}
#start_button {
border: 0;
background-color:transparent;
padding: 0;
}
</style>
</head>
<body>
<div id="page">
<a id="top"><img src="images/logo.jpg" alt="Wake Tech Credit Union" />
<div id="navigation">
<a href="index.html">HOME</a>
<a href="tools.html">TOOLS</a>
<a href="highlights.html">HIGHLIGHTS</a>
<a href="hours.html">HOURS</a>
<a href="contact.html">CONTACT</a>
<a>FEEDBACK</a>
</div>
<h1>Feedback</h1>
<div id="info">
<p id="info_start">We would like to hear from you. Click on the microphone icon and begin speaking.</p>
<p id="info_speak_now">Speak now.</p>
<p id="info_no_speech">No speech was detected. You may need to adjust your
<a href="//support.google.com/chrome/bin/answer.py?hl=en&amp;answer=1407892">
microphone settings</a>.</p>
<p id="info_no_microphone">
No microphone was found. Ensure that a microphone is installed and that
<a href="//support.google.com/chrome/bin/answer.py?hl=en&amp;answer=1407892">
microphone settings</a> are configured correctly.</p>
<p id="info_allow">Click the "Allow" button above to enable your microphone.</p>
<p id="info_denied">Permission to use microphone was denied.</p>
<p id="info_blocked">Permission to use microphone is blocked. To change,
go to chrome://settings/contentExceptions#media-stream</p>
<p id="info_upgrade">Web Speech API is not supported by this browser.
Upgrade to <a href="//www.google.com/chrome">Chrome</a>
version 25 or later.</p>
</div>
<div class="right">
<button id="start_button">
<img id="start_img" src="images/mic.gif" alt="Start"></button>
</div>
<div id="results">
<span id="final_span" class="final"></span>
<span id="interim_span" class="interim"></span>
<p>
</div>
<div class="center">
<button id="send_button" class="button">
Send Feedback</button>
<div id="send_info" class="info">
We appreciate your feedback.
</div>
<p>
<div id="div_language">
<select id="select_language"></select>
<select id="select_dialect"></select>
</div>
</div>
<script>
var langs =
[['Afrikaans', ['af-ZA']],
['Bahasa Indonesia',['id-ID']],
['Bahasa Melayu', ['ms-MY']],
['Català', ['ca-ES']],
['eština', ['cs-CZ']],
['Deutsch', ['de-DE']],
['English', ['en-AU', 'Australia'],
['en-CA', 'Canada'],
['en-IN', 'India'],
['en-NZ', 'New Zealand'],
['en-ZA', 'South Africa'],
['en-GB', 'United Kingdom'],
['en-US', 'United States']],
['Español', ['es-AR', 'Argentina'],
['es-BO', 'Bolivia'],
['es-CL', 'Chile'],
['es-CO', 'Colombia'],
['es-CR', 'Costa Rica'],
['es-EC', 'Ecuador'],
['es-SV', 'El Salvador'],
['es-ES', 'España'],
['es-US', 'Estados Unidos'],
['es-GT', 'Guatemala'],
['es-HN', 'Honduras'],
['es-MX', 'México'],
['es-NI', 'Nicaragua'],
['es-PA', 'Panamá'],
['es-PY', 'Paraguay'],
['es-PE', 'Perú'],
['es-PR', 'Puerto Rico'],
['es-DO', 'República Dominicana'],
['es-UY', 'Uruguay'],
['es-VE', 'Venezuela']],
['Euskara', ['eu-ES']],
['Français', ['fr-FR']],
['Galego', ['gl-ES']],
['Hrvatski', ['hr_HR']],
['IsiZulu', ['zu-ZA']],
['Íslenska', ['is-IS']],
['Italiano', ['it-IT', 'Italia'],
['it-CH', 'Svizzera']],
['Magyar', ['hu-HU']],
['Nederlands', ['nl-NL']],
['Norsk bokmål', ['nb-NO']],
['Polski', ['pl-PL']],
['Português', ['pt-BR', 'Brasil'],
['pt-PT', 'Portugal']],
['Român', ['ro-RO']],
['Slovenina', ['sk-SK']],
['Suomi', ['fi-FI']],
['Svenska', ['sv-SE']],
['Türkçe', ['tr-TR']],
['', ['bg-BG']],
['P', ['ru-RU']],
['', ['sr-RS']],
['', ['ko-KR']],
['', ['cmn-Hans-CN', ' ()'],
['cmn-Hans-HK', ' ()'],
['cmn-Hant-TW', ' ()'],
['yue-Hant-HK', ' ()']],
['', ['ja-JP']],
['Lingua latna', ['la']]];
for (var i = 0; i < langs.length; i++) {
select_language.options[i] = new Option(langs[i][0], i);
}
select_language.selectedIndex = 6;
updateCountry();
select_dialect.selectedIndex = 6;
showInfo('info_start');
function updateCountry() {
for (var i = select_dialect.options.length - 1; i >= 0; i--) {
select_dialect.remove(i);
}
var list = langs[select_language.selectedIndex];
for (var i = 1; i < list.length; i++) {
select_dialect.options.add(new Option(list[i][1], list[i][0]));
}
select_dialect.style.visibility = list[1].length == 1 ? 'hidden' : 'visible';
}
var send_feedback = false;
var final_transcript = '';
var recognizing = false;
var ignore_onend;
var start_timestamp;
if (!('webkitSpeechRecognition' in window)) {
upgrade();
} else {
start_button.style.display = 'inline-block';
var recognition = new webkitSpeechRecognition();
recognition.continuous = true;
recognition.interimResults = true;
recognition.onstart = function() {
recognizing = true;
showInfo('info_speak_now');
start_img.src = 'images/mic-animate.gif';
};
recognition.onerror = function(event) {
if (event.error == 'no-speech') {
start_img.src = 'images/mic.gif';
showInfo('info_no_speech');
ignore_onend = true;
}
if (event.error == 'audio-capture') {
start_img.src = 'images/mic.gif';
showInfo('info_no_microphone');
ignore_onend = true;
}
if (event.error == 'not-allowed') {
if (event.timeStamp - start_timestamp < 100) {
showInfo('info_blocked');
} else {
showInfo('info_denied');
}
ignore_onend = true;
}
};
recognition.onend = function() {
recognizing = false;
if (ignore_onend) {
return;
}
start_img.src = 'images/mic.gif';
if (!final_transcript) {
showInfo('info_start');
return;
}
showInfo('');
if (window.getSelection) {
window.getSelection().removeAllRanges();
var range = document.createRange();
range.selectNode(document.getElementById('final_span'));
window.getSelection().addRange(range);
}
if (send_feedback) {
send_feedback = false;
sendFeedback();
}
};
recognition.onresult = function(event) {
var interim_transcript = '';
for (var i = event.resultIndex; i < event.results.length; ++i) {
if (event.results[i].isFinal) {
final_transcript += event.results[i][0].transcript;
} else {
interim_transcript += event.results[i][0].transcript;
}
}
final_transcript = capitalize(final_transcript);
final_span.innerHTML = linebreak(final_transcript);
interim_span.innerHTML = linebreak(interim_transcript);
if (final_transcript || interim_transcript) {
showButtons('inline-block');
}
};
}
function upgrade() {
start_button.style.visibility = 'hidden';
showInfo('info_upgrade');
}
var two_line = / /g;
var /g;
function linebreak(s) {
return s.replace(two_line, '<p></p>').replace(one_line, '<br>');
}
var first_char = /S/;
function capitalize(s) {
return s.replace(first_char, function(m) { return m.toUpperCase(); });
}
function sendFeedback() {
/*
var n = final_transcript.indexOf(' ');
if (n < 0 || n >= 80) {
n = 40 + final_transcript.substring(40).indexOf(' ');
}
var subject = encodeURI(final_transcript.substring(0, n));
var body = encodeURI(final_transcript.substring(n + 1));
window.location.href = 'mailto:?subject=' + subject + '&body=' + body;
*/
//alert("Your feedback has been sent. Thank you!");
var feedbackform = document.createElement("FORM");
feedbackform.name="feedbackform";
feedbackform.method = "POST";
feedbackform.action = "/feedback";
var forminput = document.createElement("INPUT");
forminput.type = "TEXT";
forminput.name = "feedback";
forminput.value = final_transcript;
feedbackform.appendChild(forminput);
document.body.appendChild(feedbackform); // added for newer browsers
feedbackform.submit();
}
function sendButton() {
if (recognizing) {
send_feedback = true;
recognizing = false;
recognition.stop();
} else {
sendFeedback();
}
send_button.style.display = 'none';
send_info.style.display = 'inline-block';
showInfo('');
}
function startButton(event) {
if (recognizing) {
recognition.stop();
return;
}
final_transcript = '';
recognition.lang = select_dialect.value;
recognition.start();
ignore_onend = false;
final_span.innerHTML = '';
interim_span.innerHTML = '';
start_img.src = 'images/mic-slash.gif';
showInfo('info_allow');
showButtons('none');
start_timestamp = event.timeStamp;
}
function showInfo(s) {
if (s) {
for (var child = info.firstChild; child; child = child.nextSibling) {
if (child.style) {
child.style.display = child.id == s ? 'inline' : 'none';
}
}
info.style.visibility = 'visible';
} else {
info.style.visibility = 'hidden';
}
}
var current_style;
function showButtons(style) {
if (style == current_style) {
return;
}
current_style = style;
//copy_button.style.display = style;
send_button.style.display = style;
//copy_info.style.display = 'none';
send_info.style.display = 'none';
}
</script>
</div>
</body>
</html>
You need to submit only the modified app.js file..
I already downloaded the moment model.
Explanation / Answer
Node.js makes it possible to write applications in JavaScript on the server.It's built on the V8 JavaScript runtime and written in C++ - so it's fast.Originally, it was intended as a server environment for applications, but developers started using it to create tools to aid them in local task automation. Since then, a whole new ecosystem of Node-based tools ( such as Grunt, Gulp and Webpack ) has envolved to transform the face of front-end development.
To make use of these tools ( or packages) in Node.js we need to be able to install and manage them in a useful way. This is where npm, the Node package manager, comes in. It installs the packages you want to use and provides a useful interface to work with them.
You might consider installing Node using a version manager. This negates the permission issue raised in the next section.
let's see where node was installed and check the version.
$ which node /usr/bin/node $ node -- version v6.10.3
To verify that your installation was successful let's give Node's REPL a try.
$ node >console.log("Node is running'); Node is running > .help .break Sometimes you get stuck, this gets you out .clear Alias for .break .exit Exit the repl .help Show repl options .load Load JS from a file into the REPL session .save Save all evaluated commands in this REPL session to a file > .exit
The Node.js installation worked, so we can now focus our attention on npm, which was included in the install.
$ which npm /usr/bin/npm $ npm -- version 3.10.10
Node Packaged Modules
npm can install packages in local or global mode. In local mode it installs the package in a node_modules folder in your parent working directory. This location is owned by the current user. Global packages are installed in {prefix}/lib/node_modules/ which is owned by root ( where {prefix} is usually /usr/ or /usr/local). This means you would have to use sudo to install packages globally, which could cause permission errors when resolving third-party dependencies, as well as being a security concern. Lets change that:
Changing the Location of Global Packages
Let's see what output npm config gives us.
$ npm config list ; cli configs user-agent = "npm/3.10.10 node/v6.10.3 linux x64"
;userconfig /home/sitepoint/.npmrc prefix = "/home/sitepoint/.node_modules_global"
; node bin location = /usr/bin/nodejs ; cwd = /home/sitepoint ; HOME = /home/sitepoint ; "npm config is -I" to show all defaults.
Installing Packages in Global Mode
At the moment we only have one package installed globally - that is the npm package itself. So let's change that and install UglifyJs (a JavaScript minification tool). We use the --global flag, but this can be abbreviated to -g.
$ npm install uglify-js --global /home/sitepoint/.node_modules_global/ bin/uglifyjs -> /home/sitepoint/ .node_modules_global/lib/ node_modules/uglify-js/bin/uglifyjs + uglify-js@3.0.15 added 4 packages in 5.836s
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.