How do I deal with static navbars in Node? - html

A bit about my background: I haven't done much web development for a while, and am only recently starting to get back in the swing of things. I remember the days when I used to have static header/footer files in PHP, and code like so:
<html>
<head>
<title>Title</title>
</head>
<body>
<?php include("header.php") ?>
Body text here
<?php include("footer.php") ?>
</body>
</html>
I'm currently making the switch to Node for my backend (for various reasons not pertinent to this post). I'm still quite new at this, so I'm wondering if there is a simple way to go about having static headers/footers (which contains navbars and such) for my front end. I'm trying to use Bootstrap for my front end framework.
I think using Jade, or other template engines, might be one way to go about doing this, though I'm not necessarily sure if I want to use Jade just yet as dealing with js and HTML is troublesome enough without adding another pseudo-language/format/template into the mix. So I'm wondering if there is a solution that does not use template engines.
Here's what I currently have for my app.js/web.js file:
var express = require('express')
var app = express()
var path = require('path')
var fs = require('fs');
var bodyparser = require('body-parser')
app.use(bodyparser.urlencoded({extended: false}))
app.use(express.static(path.join(__dirname)));
app.get('/submit', function(req,res) {
[functions omitted for brevity]
})
[other processes omitted for brevity]
app.listen(8080)
Thank you!

I would highly recommend to use a view engine for this. Node is not like PHP. PHP scripts are processed sequentially and the rendered output is sent as the response. If you were to do the same approach in node you would be building a string in JavaScript and then sending it out to the client.
app.get('/submit', function(req,res) {
var output = '<html>';
output += '<head>';
...
res.send(output);
});
Now imagine that you have to query a database:
app.get('/submit', function(req,res) {
var output = '<html>';
output += '<head>';
...
db.query(query, function(err, result) {
output += 'the result is ' + result;
...
res.send(output);
});
});
So the lesson is, use a templating engine as they are designed for building the html output for you. Start with ejs as it will have a more familiar syntax to php.

Related

render JSON response using Jade

i have gone back to basics to try and create a simple example of calling a REST API, receiving some JSON back and rendering the JSON data in HTML using Jade.
I have tried many approaches to this but cannot get any to work.
what code would i need to add to my main script file (below - lxrclient.js) to achieve this. I know i need to add express module, and render the view, but no matter who may approaches i have tried i cannot get it to work. I have also added the jade file i am using further down. really appreciate any help anyone can provide with this.
//this is my main script file lxrclient3.js
var http = require('http');
var express = require('express');
var app = express();
app.set('view engine', 'jade');
var options = {
host: '41.193.214.130',
port: 2510,
path: '/eiftidemo/clt_list',
method: 'GET'
};
http.request(options, function(res) {
var body = '';
//node of these statemnst excecute
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
var clientsData = JSON.parse(body);
debugger;
});
}).end();
app.get("/clientlist", function(req, res){
res.render('listlxr', {clientd: clientsData});
});
var server = app.listen(3000, function() {
console.log('Our App is running at http://localhost:3000');
});
here is my Jade view
html
head
title List of Clients
link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css")
body
div.row
div.col-md-3
div.col-md-6
div.panel.panel-primary
div.panel-heading.text-center
h1 Client List for Hyposure
div.panel-body
table.table
each clients in clientsData
tr
td.media
span.bg-info= clients.clientName
td.media
span.bg-info= clients.clientSurname
thx to anyone who can help
First of all, when you say Jade I hope you mean Pug, if not, you should update to the newest version of Pug instead.
Now, to send data to your template for the engine to render you send a JSON object, like so;
res.get("/", function(req, res)
{
res.render("page.html", {greet : "Hello"});
}
This is a standard way of rendering a page and sending some data along side.
Now in your Pug (Jade (Same thing)) template you can access the sent variable like so;
html
head
title List of Clients
body
h1 #{greet} <!-- This will print "Hello" -->
This should give you a basic idea on how to render data onto a site, you can also send nested objects and you just work it the same way as in this example, but you point to the correct key. So for example if you're sending the following object:
{
greet: {
message : "Hello",
who : "Adrian"
}
}
Then you can print values from that using:
#{greet.message} #{greet.who}

Referencing resources in a global way either from a virtual directory or the web root?

Let's say I have an MVC/WebAPI/AngularJS site that I'm running locally, e.g. ;
localhost/Test/
which I then want to move to
www.test.com
While local, I have a lot of references to various directories (jsfiles, etc) of the following format (in either JS or HTML files)
app.directive('rpdbSpinner', function() {
return {
restrict: 'E',
**templateUrl: '/Test/templates/directives/spinner.html',**
scope: {
isLoading:'='
}
}
})
when updating/web publishing, I'd have to change everything to:
app.directive('rpdbSpinner', function() {
return {
restrict: 'E',
**templateUrl: '/templates/directives/spinner.html',**
scope: {
isLoading:'='
}
}
})
I can do this manually (which is what I've been doing),but the larger the project grows, the harder it becomes. I could, of course, only change it once and then excluded the files during publishing phase (web.config/rest), but it still feels like I am going about it the wrong way. Using "~/" wouldn't work on plain HTML/JS files as far as I'm aware, and this I can't really use it...
Any suggestions to map to paths globally regardless of whether in a Virtual Directory or the root of a project?
Thanks :)
If you simply care about getting the root/base url of the site so you can append that to get the other url you are after, you may simply use / as the first character of your url.
var getUsersUrl = "/api/users";
Here is an alternate approach if you want more than just the app root (Ex : Specific urls( built using mvc helper methods such as Url.RouteUrl etc)
You should not hard code your app base path like that. You may use the Url.Content or Url.RouteUrl helper methods in your razor view to generate the url to the app base. It will take care of correctly building the url regardless of your current page/path.Once you get this value, assign it to a javascript variable and use that in your other js code to build your other urls. Always make sure to use javascript namespacing when doing so to avoid possible issues with global javascript variables.
So in your razor view (Layout file or specific view), you may do this.
<script>
var myApp = myApp || {};
myApp.Urls = myApp.Urls || {};
myApp.Urls.baseUrl = '#Url.Content("~")';
myApp.Urls.userListUrl = '#Url.Action("Index","User")';
</script>
<script src="~/Scripts/NonAngularJavaScript.js"></script>
<script src="~/Scripts/AngularControllerForPage.js"></script>
<script>
var a = angular.module("app").value("appSettings", myApp);
</script>
In your angular controller, you can access it like,
var app = angular.module("app", []);
var ctrl = function (appSettings) {
var vm = this;
console.log(appSettings.Urls.userListUrl);
vm.baseUrl = appSettings.Urls.baseUrl;
//build other urls using the base url now
var getUsersUrl = vm.baseUrl + "api/users";
console.log(getUsersUrl);
};
app.controller("ctrl", ctrl)
You can also access this in your data services, directives etc.
In your non angular java script files.
// With the base url, you may safely add the remaining url route.
var urlToJobIndex2= myApp.Urls.baseUrl+"jobs/GetIndex";
Using "~/" wouldn't work on plain HTML/JS files as far as I'm aware,
and this I can't really use it...
Yes, but you could inject it in your main server-side served webpage as a variable:
<script>
var baseUrl = ... get the base url from the server using ~/
</script>
and then in your external scripts simply concatenate the relative urls with it. As far as static html files are concerned, then it could be a little more problematic. You could serve them through some special server side handler that will take care of injecting this logic.
You can use module.constant to create an injectable which you can use.
app.constant("URL_BASE", "/Test");
app.directive('rpdbSpinner', function(URL_BASE) {
return {
restrict: 'E',
**templateUrl: URL_BASE + '/templates/directives/spinner.html',**
scope: {
isLoading:'='
}
}
})
You can also use module.value if you register it before you register your directive.
For more information see AngularJS Module Guide -- configuration.

How to scrape badly formed HTML

I'm trying to scrape a really really old page that looks like it was built with FrontPage or even just pasted from a Word document. It's full of font tags that can spontaneously stop and start in the middle of a word, or similar elements at randomly different tree depths.
I am not looking for any tools that can parse poor XML, I am already using Html Agility Pack. When I say badly formed HTML I mean it was not outputted from a database, does not have any consistent patterns, but on the screen it looks fine.
What techniques and tools can I use?
I would use cheerio in Nodejs. It replicates the same api as jQuery which makes it very easy to parse bad formatted html. Scraping with Javascript makes sense for many reasons.
This is an example taken from node.io,
var request = require('request')
, cheerio = require('cheerio')
, async = require('async')
, format = require('util').format;
var reddits = [ 'programming', 'javascript', 'node' ]
, concurrency = 2;
async.eachLimit(reddits, concurrency, function (reddit, next) {
var url = format('http://reddit.com/r/%s', reddit);
request(url, function (err, response, body) {
if (err) throw err;
var $ = cheerio.load(body);
$('a.title').each(function () {
console.log('%s (%s)', $(this).text(), $(this).attr('href'));
});
next();
});
});

How to configure my HTML to use i18next?

I have an application with nodejs, express and HTML on client side. I'd like to internalize my project using i18next. On nodejs side, it's ok, I required i18next and started it.
var i18n = require('i18next'),
app = express();
i18n.registerAppHelper(app);
i18n.init({lng: "en-US"}, function(t){
var trad = i18n.t("trad.key1");
console.log("trad = " + trad);
});
In console log, I have the traduction of translation.json to variable trad.key1. It is correct.
Know, the question: what I need to do to use i18next on client side, HTML page? I found some examples to do this, but using jQuery, and I don't use that.
Thanks for help.
It's done.
On HTML file, I needed to reference i18next.js and init i18n, like below. On init i18n, I specified the correct translation.json, as can you see.
<script type="text/javascript" src="i18next/i18next.js"></script>
<script>
window.onload = function() {
i18n.init({
lng: "en-US",
resGetPath:"locales/__lng__/translation.json"
},function(t) {
var translate = i18n.t("var.key1");
});
};
</script>
That's all.

Node.js : How to embed Node.js into HTML?

In a php file I can do:
<p><?php echo "hello!";?></p>
Is there a way to do this in node, if yes what's the logic for it?
I have an idea how could this be done:
Use an identifier markup for node in the HTML file like: <node>code</node>
Load & Parse HTML file in Node
Grab node markup from the HTML file and run it
But I'm not sure if this is the best way or even if it works :)
Please note I want to learn node.js, so express and other libraries and modules are not answers for me, because I want to know the logic of the process.
What your describing / asking for a node.js preprocessor. It does exist but it's considered harmful.
A better solution would be to use views used in express. Take a look at the screencasts.
If you must do everything from scratch then you can write a micro templating engine.
function render(_view, data) {
var view = render.views[view];
for (var key in data) {
var value = data[key];
view.replace("{{" + key + "}}", value);
}
return view;
}
render.views = {
"someView": "<p>{{foo}}</p>"
};
http.createServer(function(req, res) {
res.end(render("someView", {
"foo": "bar"
}));
});
There are good reasons why mixing php/asp/js code directly with HTML is bad. It does not promote seperation of concerns and leads to spaghetti code. The standard method these days is templating engines like the one above.
Want to learn more about micro templating? Read the article by J. Resig.
You can try using JooDee, a node webserver which allows you to embed serverside javascript in your web pages. If you are familiar with Node and PHP/ASP, it is a breeze to create pages. Here's a sample of what a page looks like below:
<!DOCTYPE html>
<html>
<: //server side code in here
var os = require('os');
var hostname = os.hostname();
:>
<body>
<div>Your hostname is <::hostname:></div>
</body>
</html>
Using JooDee also lets you expose server javascript vars to the client with no effort by attaching attributes to the 'Client' object server side, and accessing the generated 'Client' object in your client side javascript.
https://github.com/BigIroh/JooDee
Use a template engine. From terminal
npm install ejs
In code:
var ejs = require('ejs');
var options = {
locals: {
foo: function() { return "bar"; }
}
};
var template = "<p><%= foo() %></p>";
console.log(ejs.render(template, options));