Is there a node.js method to read an index.html file and add new elements? - node.js

I am trying to read my index.html file from my server.js in order to add a new that links to a new html file I generate. I am using the POST method to do this and can successfully generate the new HTML file, however I am not sure how I can add a new inside the index.HTML.
Here is my server.js:
//POST method
if(req.method === 'POST'){
req.on('data', (data) => {
let elementObj = querystring.parse(data.toString());
element = elementObj.elementName;
elementSymbol = elementObj.elementSymbol;
elementAtomic = elementObj.elementAtomicNumber;
elementDescription = elementObj.elementDescription;
let newElement = fs.createWriteStream(`./public/${element}.html`);
newElement.write(`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>The Elements - ${element}</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<h1>${element}</h1>
<h2>${elementSymbol}</h2>
<h3>Atomic number ${elementAtomic}</h3>
<p>${elementDescription}</p>
<p>back</p>
</body>
</html>`);
let indexElements = document.querySelector('#elements');
let li = document.createElement('li');
let a = document.createElement('a');
a.setAttribute('href', `/${element}.html`);
let elem = document.querySelector(`a[href = "/${element}.html"]`);
elem.innerHTML = `${element}`;
indexElements.appendChild(li);
li.appendChild(a);
res.end(data);
});
}
Here is my index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>The Elements</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<h1>The Elements</h1>
<h2>These are all the known elements.</h2>
<h3>These are 2</h3>
<ol id = 'elements'>
<li>
Hydrogen
</li>
<li>
Helium
</li>
</ol>
<script src="../../server.js"></script>
</body>
</html>
The result I want in my newly, modified index.html (new 'Boron' <li> added):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>The Elements</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<h1>The Elements</h1>
<h2>These are all the known elements.</h2>
<h3>These are 2</h3>
<ol id = 'elements'>
<li>
Hydrogen
</li>
<li>
Helium
</li>
<li>
Boron
</li>
</ol>
<script src="../../server.js"></script>
</body>
</html>

Your question doesn't make it clear exactly what you're trying to do, but if these are your requirements:
You want to have an HTML template on disk.
That you can insert some content into based on some dynamic data.
You can't use anything other than plain node.js http server (so no existing template engines).
Then, you essentially have to build your own little template engine. You can do that by reading the file into memory and then doing some sort of search/replace on some markers in the file to insert your content and then send that newly formed content. Here's a general idea for how to do that:
Contents of template.html file on disk
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>The Elements</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<h1>The Elements</h1>
<h2>These are all the known elements.</h2>
<h3>These are 2</h3>
<ol id='elements'>
<li>
Hydrogen
</li>
<li>
Helium
</li>
<!-- new elements -->
</ol>
<script src="../../server.js"></script>
</body>
</html>
Server code for handling the POST
//POST method
if(req.method === 'POST'){
req.on('data', (data) => {
let elementObj = querystring.parse(data.toString());
let element = elementObj.elementName;
let elementSymbol = elementObj.elementSymbol;
let elementAtomic = elementObj.elementAtomicNumber;
let elementDescription = elementObj.elementDescription;
fs.readFile("template.html", function(err, data) {
if (err) return res.status(500).end();
// build new content
let newContent = "<li><a href=${element}.html>${element}</a></li>";
data = data.replace(/<!-- new elements -->/, newContent);
res.send(data);
});
});
});

Related

How to pass data from java script to html?

app.post('/result',(req, res) =>{
const n = req.body.fname
res.sendFile(__dirname + '/result.html', {n:n})
})
I want to transfer n to result.html file. My result.html file is below. This code is not working
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Title</title>
</head>
<body>
<p> <%= n %></p>
</body>
</html>
You should change your html as below, by adding and id for the p tag
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Title</title>
</head>
<body>
<p id="displayPtag"> <%= n %></p>
</body>
</html>
Use the below code in your javascript
document.getElementById("displayPtag").innerHTML = n;

Adding CSS File to ejs tempelate using variable from server side

I am trying to add css file dynamically in ejs tempelate.
I know how to include ejs file but not getting how to add css file dynamically.
Code :-
Index.js
router.get('/', function(req, res, next) {
res.render('template', { title: 'abc',page:'index',cssa:'home'});
});
template.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="/stylesheets/style.css">
<!-- Here I want to add home.css file -->
</head>
<body>
<!-- including my ejs file -->
<%- include(page) %>
</body>
</html>
I tried :
<link rel="stylesheet" type="text/css" href="/stylesheets/\<%= cssa %>\" >
<% include %><%= cssa %><% .css %>
Goal:
to pass the server side received variable(cssa) in stylesheet source.
Don't need to concat the css path and variable, you can also do it as follows:
<link rel='stylesheet' href='/stylesheets/<%= yourVariableName %>.css' />
Method to include :
<% var css_link = '/stylesheets/' + cssa + '.css'; %>
<link rel="stylesheet" type="text/css" href="<%= css_link %>" >
Credit goes to #SpiRT
Alternatively :
<link rel="stylesheet" type="text/css" href="/stylesheets/<%=cssa%>.css">
I've found it most convenient to inject custom css scripts through an array which can then be processed in the ejs template.
This method would allow you to render any amount of CSS files that are additionally required (example, you have a site that uses 1 standard css across all pages but have 1 or 2 page specific ones which can then be included in the model passed through the ejs renderer to that specific page/route).
In the example it's a given that the css files are in the same folder, however that can be changed to each one's liking:
router side:
router.get( ... {
model = {};
model.Stylesheets = [];
model.Stylesheets.push("stylefile");
res.render("view",{model:model});
});
with the custom stylesheets being pushed though to the view, then the ejs files can be something like:
<%
var customStylesheets = "";
model.Stylesheets.forEach(function(style){
customStylesheets+='<link type="text/css" rel="stylesheet" href="css/'+style+'.css">';
})
%>
<!DOCTYPE html>
<html>
<head>
<title><%= model.title %></title>
<link type="text/css" rel="stylesheet" href="css/standard.css">
<%- customStylesheets %>
...
</head>

popup.html view not updating the newly assigned values of $scope variables in controller in popup.js

I'm trying to build an extension that scrapes email IDs from a webpage. The problem is that...
The popup.html view is not updating the new values of $scope.emailList and $scope.count in the controller in popup.js. However, when I do Inspect Popup it displays the new values attached to the $scope variables but I see no errors that I can look into and work on.
popup.js
var app = angular.module('emailScraper',[]);
app.controller('AppCtrl', ['$scope', '$http', function($scope, $http) {
//Fetch URL of current Tab open in Chrome
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
// and use that tab to fill in out title and url
var tab = tabs[0];
$scope.cpUrl = tab.url;
console.log($scope.cpUrl); //I SEE ONLY THIS LINE WHEN I INSPECT POPUP
});
$scope.appLoaded = false;
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log("Message received: ", request); //I SEE ONLY IN Inspect Popup BUT NOT IN popup.html view
$scope.emailList = request;
$scope.count = Object.keys($scope.emailList).length;
console.log("Emails found: " + $scope.count); //I SEE ONLY IN Inspect Popup BUT NOT IN popup.html view
$scope.appLoaded = true;
sendResponse({status: "Received JSON data!"});
});
}]);
content script - relevant portion
var jsonData = scrape(); // scrape() is included in the Content Script which I've chosen to leave out here.
console.log(jsonData);
chrome.runtime.sendMessage(jsonData, function(response) {
console.log(response);
});
background.js
var background = {
injectScript: function() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.executeScript(tabs[0].id, {file: "myscript.js"});
});
}
};
background.injectScript();
popup.html
<!DOCTYPE html>
<html ng-app="emailScraper">
<head>
<!--
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<link rel="stylesheet" href="css/lib/concise-v3.4.0-UI-dist/concise.min.css">
-->
<link rel="stylesheet" href="css/lib/materialize/materialize.min.css" media="screen,projection">
<link rel="stylesheet" href="css/app/popup.css">
</head>
<body ng-controller="AppCtrl">
<div id="popWindow">
<div class="navbar-fixed">
<nav>
<div class="nav-wrapper">
<h5 class="brand-logo">Email Scraper</h5>
<span class="badge">
<a># found </a>
<a>{{count}}</a>
</span>
</div>
</nav>
</div>
<div class="progress" ng-hide="appLoaded">
<div class="indeterminate"></div>
</div>
<div class="progress" ng-show="appLoaded">
<div class="determinate" style="width: 100%"></div>
</div>
<div class="collection" ng-if="count > 0">
<h6>{{email}}</h6>
</div>
<div ng-if="count === 0">
<p class="flow-text"> Sorry, No Email IDs found.</p>
</div>
</div>
<script type="text/javascript" src="js/lib/jquery/jquery.min.js"></script>
<script type="text/javascript" src="js/lib/angular_1.5.6/angular.min.js"></script>
<script type="text/javascript" src="js/lib/materialize/materialize.min.js"></script>
<script type="text/javascript" src="js/app/popup.js"></script>
</body>
</html>

gulp-rev-replace isn't changing the revisioned file names in my master.blade.php

I've been trying to create a build system using gulp in a Laravel project and the only problem left right now is renaming the right file names inside my master.blade.php file. As it is now, it's only following the filenames provided in the gulp-useref parameters, but the files revisioned by gulp-rev are not replaced by gulp-rev-replace.
Here is my gulp task:
gulp.task('build', ['clean', 'scss', 'js', 'master'], function() {
var assets,
jsFilter = $.filter('**/*.js'),
cssFilter = $.filter('**/*.css');
return gulp.src('app/views/layouts/master.blade.php')
.pipe(assets = $.useref.assets({searchPath: '/'}))
.pipe(jsFilter)
.pipe($.uglify())
.pipe(jsFilter.restore())
.pipe(cssFilter)
.pipe($.csso())
.pipe(cssFilter.restore())
.pipe($.rev())
.pipe(assets.restore())
.pipe($.useref())
.pipe($.revReplace())
.pipe($.rename(function(path) {
if(path.extname === '.php') {
path.dirname = 'app/views/layouts';
} else {
path.dirname = 'public/assets';
}
}))
.pipe(gulp.dest('./'))
.pipe($.size({title: 'build files', showFiles: true}))
.on('end', function() {
setTimeout(function() {
// force watchify to close all watchers
process.exit();
});
});
});
The default master.blade.php would look like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{$title}}</title>
<!-- build:css assets/index.css -->
<!-- bower:css -->
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.css" />
<!-- endbower -->
<link rel="stylesheet" href="/.tmp/index.css">
<!-- endbuild -->
</head>
<body>
<section id="container">
<header>
#include('layouts.navbar')
</header>
<aside>
#include('layouts.sidebar')
</aside>
<section>
#yield('content')
</section>
<footer>
#include('layouts.footer')
</footer>
</section>
<!-- build:js assets/index.js -->
<!-- bower:js -->
<script src="/bower_components/jquery/dist/jquery.js"></script>
<script src="/bower_components/lodash/dist/lodash.compat.js"></script>
<!-- endbower -->
<script src="/.tmp/index.js"></script>
<!-- endbuild -->
</body>
</html>
and the result will always look like this despite the gulp-rev-replace pipe.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{$title}}</title>
<link rel="stylesheet" href="assets/index.css">
</head>
<body>
<section id="container">
<header>
#include('layouts.navbar')
</header>
<aside>
#include('layouts.sidebar')
</aside>
<section>
#yield('content')
</section>
<footer>
#include('layouts.footer')
</footer>
</section>
<script src="assets/index.js"></script>
</body>
</html>
I figured out the problem, The gulp-rev-replace documentation mentions that they only replace files with extensions ['.js', '.css', '.html', '.hbs'] by default. By passing ['.php'] in the replaceInExtensions option.

YUI3 find current tab in TabView

I'm using YUI3 TabView component, and I'd like to be able to get the index of the currently selected tab. I've been looking through the api docs, but can't seem to find the relevant way to do this.
http://developer.yahoo.com/yui/3/api/module_tabview.html
Thanks!
"indexOf" actually works if you use the "tabview.get('selection')" as the argument.
Example:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Untitled Document</title>
<script type="text/javascript" charset="utf-8"
src="http://yui.yahooapis.com/3.2.0/build/yui/yui-min.js">
</script>
</head>
<body>
<body class="yui3-skin-sam">
<p id="msg"></p>
<input type='button' value='Button' id='button'/>
<div id="demo">
<ul>
<li>foo</li>
<li>bar</li>
<li>baz</li>
</ul>
<div>
<div id="foo">foo content</div>
<div id="bar">bar content</div>
<div id="baz">baz content</div>
</div>
</div>
<script>
var YUI;
YUI().use('event', 'node', 'tabview', function (Y) {
Y.one('#msg').set('innerHTML', 'message area');
var tabview = new Y.TabView({srcNode: '#demo'});
tabview.render();
var displayIndex = function (tabview) {
var sel = tabview.get('selection');
var idx = tabview.indexOf(sel);
Y.one('#msg').set('innerHTML', 'Selected Tab Index = ' + idx);
}
displayIndex(tabview);
Y.after('click', function(e) {
displayIndex(this);
},'body',tabview);
});
</script>
</body>
</html>

Resources