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));
Related
I've just started using VueJS and I'm really liking it! :) I would like to save the values in the querystring to a VueJS variable - this is something super simple in handlebars + express, but seems more difficult in Vue.
Essentially I am looking for something similar to -
http://localhost:8080/?url=http%3A%2F%2Fwww.fake.co.uk&device=all
const app = new Vue({
...
data: {
url: req.body.url,
device: req.body.device
}
...
});
Google seemed to point me to vue-router, but I'm not sure if that's really what I need/how to use it. I'm currently using express to handle my backend logic/routes.
Thanks,
Ollie
You can either to put all your parameters in hash of the url, e.g.:
window.location.hash='your data here you will have to parse to'
and it will change your url - the part after #
Or if you insist to put them as query parameters (what's going after ?) using one of the solutions from Change URL parameters
You can use URLSearchParams and this polyfill to ensure that it will work on most web browsers.
// Assuming "?post=1234&action=edit"
var urlParams = new URLSearchParams(window.location.search);
console.log(urlParams.has('post')); // true
console.log(urlParams.get('action')); // "edit"
console.log(urlParams.getAll('action')); // ["edit"]
console.log(urlParams.toString()); // "?post=1234&action=edit"
console.log(urlParams.append('active', '1')); // "?post=1234&action=edit&active=1"
Source:
https://davidwalsh.name/query-string-javascript
URLSearchParams
https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
https://github.com/WebReflection/url-search-params/blob/master/build/url-search-params.js
See also:
https://stackoverflow.com/a/12151322/194717
I'm working on an AngularJs/MVC app with Web API etc. which is using a CDN. I have managed to whitelist two URLs for Angular to use, a local CDN and a live CDN (web app hosted in Azure).
I can successfully ng-include a template from my local CDN domain, but the problem arises when I push the site to a UAT / Live environment, I cant be using a template on Localhost.
I need a way to be able to dynamically get the base url for the templates. The location on the server will always be the same, eg: rooturl/html/templates. I just need to be able to change the rooturl depending on the environment.
I was thinking if there was some way to store a global variable, possibly on the $rootScope somewhere that I can get to when using the templates and then set that to the url via Web API which will get return a config setting.
For example on my dev machine the var could be http://Localhost:52920/ but on my uat server it could be https://uat-cdn.com/
Any help would be greatly appreciated as I don't want to store Js, css, fonts etc on the CDN but not the HTML as it feels nasty.
Thanks I'm advance!
I think it's good practice to keep environment and global config stuff outside of Angular altogether, so it's not part of the normal build process and is harder to accidentally blow away during a deploy. One way is to include a script file containing just a single global variable:
var config = {
myBaseUrl: '/templates/',
otherStuff: 'whatever'
}
...and expose it to Angular via a service:
angular.module('myApp')
.factory('config', function () {
var config = window.config ? window.config : {}; // (or throw an error if it's not found)
// set defaults here if useful
config.myBaseUrl = config.myBaseUrl || 'defaultBaseUrlValue';
// etc
return config;
}
...so it's now injectable as a dependency anywhere you need it:
.controller('fooController', function (config, $scope), {
$scope.myBaseUrl = config.myBaseUrl;
}
Functionally speaking, this is not terribly different from dumping a global variable into $rootScope but I feel like it's a cleaner separation of app from environment.
If you decide to create a factory then it would look like this:
angular.module('myModule', [])
.factory('baseUrl', ['$location', function ($location) {
return {
getBaseUrl: function () {
return $location.hostname;
}
};
}]);
A provider could be handy if you want to make any type of customization during config.
Maybe you want to build the baseurl manually instead of using hostname property.
If you want to use it on the templates then you need to create a filter that reuses it:
angular.module('myModule').filter('anchorBuilder', ['baseUrl', function (baseUrl) {
return function (path) {
return baseUrl.getBaseUrl() + path;
}
}]);
And on the template:
EDIT
The above example was to create links but if you want to use it on a ng-include directive then you will have a function on your controller that uses the factory and returns the url.
// Template
<div ng-include src="urlBuilder('path')"></div>
//Controller
$scope.urlBuilder = function (path) {
return BaseUrl.getBaseUrl() + path;
};
Make sure to inject the factory in the controller
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.
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.
Our corporate wiki is Mediawiki. I have no problem to put iframe into my site to refer for some article on wiki.
But my own site have a lot of widgets and own style. I don't want to include Mediawiki navigation/search/login widgets, logo image.
Is it possible and how to get Mediawiki page contents without widgets (only article body)?
Yes, it is. You'll probably want to use the action=render url parameter, for example: http://en.wikipedia.org/w/index.php?action=render&title=Main_Page. Note that the stylesheets from the wiki aren't included, so you'll need to copy the relevant rules to your site's css files. See also this.
Thank waldir for answer!
After asking question I perform own research and end with code:
window.onload = function() {
httpRequest = new XMLHttpRequest();
httpRequest.onreadystatechange = function() {
if (httpRequest.readyState !== 4) {
console.log("Not ready, code: %o", httpRequest.readyState);
return;
}
if (httpRequest.status !== 200) {
console.log("Server error: %o", httpRequest.status);
return;
}
var json = JSON.parse(httpRequest.responseText);
console.log("json: %o", json);
var wiki = json.query.pages["1"].revisions[0]["*"];
console.log("wiki: %o", wiki);
var html = InstaView.convert(wiki);
console.log("html: %o", html);
document.getElementById('area').innerHTML = html;
};
var url = 'https://wiki.evil-company.com/api.php?action=query&prop=revisions&format=json&titles=Main_page&rvprop=timestamp|user|comment|content';
httpRequest.open('GET', url, true);
httpRequest.send(null);
}
Here I use https://github.com/cscott/instaview/blob/master/main.js project which is enhanced http://en.wikipedia.org/wiki/User:Pilaf to transform json output to HTML on browser side.
The reason for this code because our wiki is old or misconfigured and action=render is not available. But I trap into cross-domain scripting issue so I think that iframe with action=render is better solution.
See also How do you grab an article including the links in a usable format?
Another suggestion to use action=parse (http://en.wikipedia.org/w/api.php?action=parse&title=Linux) lead to warning:
You are looking at the HTML representation of the XML format.
HTML is good for debugging, but is unsuitable for application use.
Specify the format parameter to change the output format.
UPDATE
Perfect solution just append query action=render to any valid wiki URL like:
http://en.wikipedia.org/wiki/Linux?action=render