Google App Script include css from another file - css

I'm trying out Google app scripts for the first time and I'm having a nightmare trying to get it to read my Stylesheet.
I've read dozens of pages and they all say the same thing, but it just doesn't work.
This is my code.gs :-
return HtmlService.createHtmlOutputFromFile('index');
}
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
This is my index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<?!= include('Stylesheet'); ?>
</head>
<body>
Hello!!!!<br>
This is a test to see how Google scripts work<br>
</body>
</html>
This is my Stylesheet
<style>
html{
min-height:100%;
background-color:blue;
}
</style>
If I put the style tags inside the index file, it works fine, but when I try to include it, the include script just gets added to my page. I've tried using createTemplateFromFile as well, but it has the same result. It seems like index.html is ignoring the script identifier <?!
Please could someone tell me what I'm doing wrong as every page I've looked at says to do it this way!!!!!
Thanks

I assume it could be because your are not calling .evaluate()
return HtmlService.createTemplateFromFile('index').evaluate();
https://developers.google.com/apps-script/guides/html/best-practices#code.gs

Seems like it's been missed to add evaluate() function.
As per the HTML Service: Templated HTML , one should be using particular scriptlet as per the requirement.
I'd recommend a generalized solution like below:
function include(fileName, params) {
return render(fileName, params).getContent();
}
function render(path, params) {
let htmlBody = HtmlService.createTemplateFromFile(path);
// for prop drilling
htmlBody.allParams = {};
if (params) {
htmlBody.allParams = params;
Object.keys(params).forEach(key => {
htmlBody[key] = params[key];
});
}
return htmlBody.evaluate();
}

Related

CSS Issue with Node.JS / EJS

I know similar questions have been asked before, but I've had a good look through & unfortunately none of the answers are helping me.
My CSS file is being ignored in certain circumstances.
So in my app.js file I have this code, defining my view engine setup
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
In my index.js file I have the following the code for UserList page
/* GET Userlist page. */
router.get('/userlist', function(req, res) {
var db = req.db; // (1) Extract the db object we passed to our HTTP request
var collection = db.get('usercollection'); // (2) Tell our app which collection we want to use
// (3) Find (query) results are returned to the docs variable
collection.find({},{},function(e,docs){
res.render('userlist', { "userlist" : docs }); // (4) Render userlist by passing returend results to said variable
});
});
Finally, my userlist.ejs page looks like this:
<!DOCTYPE html>
<html>
<head>
<title>User List</title>
<link rel='stylesheet' href='/stylesheets/style.css' type="text/css" />
</head>
<body>
<h1>User List</h1>
<ul>
<%
var list = '';
for (i = 0; i < userlist.length; i++) {
list += '<li>' + userlist[i].username + '</li>';
}
return list;
%>
</ul>
</body>
</html>
But when I run my page the CSS file is not loaded. However if I exclude this code:
<%
var list = '';
for (i = 0; i < userlist.length; i++) {
list += '<li>' + userlist[i].username + '</li>';
}
return list;
%>
The CSS file is loaded and applied without issue. Can anyone tell me why this is please? Apologies for the newbie question, but I've been trying to figure this out for ages.
I should mention the 'h1' tags are ignored too. The only thing rendered is the list items.
Not sure if its relevant, but my app is connecting to MongoDB to return the user data.
Any assistance would be very much appreciated!
Thank you!
Make sure that your CSS file is either defined as an endpoint in your index.js file or make sure that public/stylesheets/style.css exists so it can be loaded through the app.use(express.static(path.join(__dirname, 'public'))); command.

How do I make my firebase database public

I have a database in firebase and I want to make it public like https://publicdata-transit.firebaseio.com/sf-muni
What I see here they have a prefix "pulicdata", How do I get it?
A publicly accessible read-only dashboard, like the one you're referring to, is only available for apps managed by Firebase themselves. You cannot enable it on your own applications.
This won't do any formatting (you can make it pretty if you want), but this will take your snapshot and just put it up on the screen for anyone to see as long as you have your settings for read as true.
<html>
<head>
<script src='https://cdn.firebase.com/js/client/2.2.1/firebase.js'></script>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js'></script>
</head>
<body>
<div id='displaySnapshotDiv'></div>
<script>
var myDataRef = new Firebase('https://MY-FIREBASE-NAME-GOES-HERE.firebaseio.com/');
myDataRef.on('value', function(snapshot) {
displaySnapshot(snapshot.val());
});
function displaySnapshot(snapshot) {
$('<div/>').text(JSON.stringify(snapshot)).appendTo($('#displaySnapshotDiv'));
$('#displaySnapshotDiv')[0].scrollTop = $('#displaySnapshotDiv')[0].scrollHeight;
};
</script>
</body>
</html>
If you want it to be a little more readable, you could do something like:
<!-- language: lang-html -->
<html>
<head>
<script src='https://cdn.firebase.com/js/client/2.2.1/firebase.js'></script>
<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js'></script>
</head>
<body>
<div id='displaySnapshotDiv'></div>
<script>
var myDataRef = new Firebase('https://MY-FIREBASE-NAME-GOES-HERE.firebaseio.com/');
myDataRef.on('child_added', function(snapshot) {
displaySnapshotNeatly(snapshot.val());
});
function displaySnapshotNeatly(snapshot) {
$('<div/>').text(JSON.stringify(snapshot)).appendTo($('#displaySnapshotDiv'));
};
</script>
</body>
</html>
Here is the second one working in JSFiddle: https://jsfiddle.net/lukeschlangen/rzfn45pz/
And here is the second one with your firebase data (please tell me the security settings for writing are set to something other than true?): https://jsfiddle.net/lukeschlangen/rzfn45pz/2/
It seems like you might want to do some formatting, but this is displaying all of the data.
The data can be available public if you change your database rules to true or use the auth token for authentication. But since you do not want to authenticate access, all you simply need to do is Make you access rules public
for more information check out: https://firebase.google.com/docs/reference/rest/database/
enter image description here

jsdom does not fetch scripts on local file system

This is how i construct it:
var fs = require("fs");
var jsdom = require("jsdom");
var htmlSource = fs.readFileSync("./test.html", "utf8");
var doc = jsdom.jsdom(htmlSource, {
features: {
FetchExternalResources : ['script'],
ProcessExternalResources : ['script'],
MutationEvents : '2.0'
},
parsingMode: "auto",
created: function (error, window) {
console.log(window.b); // always undefined
}
});
jsdom.jQueryify(doc.defaultView, 'https://code.jquery.com/jquery-2.1.3.min.js', function() {
console.log( doc.defaultView.b ); // undefined with local jquery in html
});
the html:
<!DOCTYPE HTML>
<html>
<head></head>
<body>
<script src="./js/lib/vendor/jquery.js"></script>
<!-- <script src="http://code.jquery.com/jquery.js"></script> -->
<script type="text/javascript">
var a = $("body"); // script crashes here
var b = "b";
</script>
</body>
</html>
As soon as i replace the jquery path in the html with a http source it works. The local path is perfectly relative to the working dir of the shell / actual node script. To be honest i don't even know why i need jQueryify, but without it the window never has jQuery and even with it, it still needs the http source inside the html document.
You're not telling jsdom where the base of your website lies. It has no idea how to resolve the (relative) path you give it (and tries to resolve from the default about:blank, which just doesn't work). This also the reason why it works with an absolute (http) URL, it doesn't need to know where to resolve from since it's absolute.
You'll need to provide the url option in your initialization to give it the base url (which should look like file:///path/to/your/file).
jQuerify just inserts a script tag with the path you give it - when you get the reference in the html working, you don't need it.
I found out. I'll mark Sebmasters answer as accepted because it solved one of two problems. The other cause was that I didn't properly wait for the load event, thus the code beyond the external scripts wasn't parsed yet.
What i needed to do was after the jsdom() call add a load listener to doc.defaultView.
The reason it worked when using jQuerify was simply because it created enough of a timeout for the embedded script to load.
I had the same issue when full relative path of the jquery library to the jQueryify function. and I solved this problem by providing the full path instead.
const jsdom = require('node-jsdom')
const jqueryPath = __dirname + '/node_modules/jquery/dist/jquery.js'
window = jsdom.jsdom().parentWindow
jsdom.jQueryify(window, jqueryPath, function() {
window.$('body').append('<div class="testing">Hello World, It works')
console.log(window.$('.testing').text())
})

Multiple sections in Handlebars template

I’m just getting to know Handlebars a bit better as a templating solution and have hit a problem that I don’t know how to solve.
I’ve added sections to my layout, one for the header and one for the footer for dynamically inserting scripts from my views. However, only the first section ever renders. The second one (regardless of order) is always omitted.
My layout is a simple HTML page:
<!doctype html>
<html>
<head>
<title>Test site</title>
{{{_sections.head}}}
</head>
<body>
<header>
//Logo and stuff here
</header>
{{{body}}}
<script src="//code.jquery.com/jquery-2.0.2.min.js"></script>
{{{_sections.footer}}}
</body>
</html>
And in my layout file I have:
{{#section 'head'}}
<script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.3.0/handlebars.min.js"></script>
{{/section}}
//basic HTML here
{{#section 'footer'}}
<script>
alert("this doesn’t fire if its second!");
</script>
{{/section}}
The header section appears on the page but the footer does not. The thing is, if I put the footer at the top of the page (i.e. before the {{section ‘head’}} that then renders but the head section no longer renders.
In my app.js I’m setting up the section functionality as follows:
var handlebars = require('express3-handlebars')
.create({
defaultLayout: 'main',
helpers: {
section: function (name, options) {
if (!this._sections) {
this._sections = {};
this._sections[name] = options.fn(this);
return null;
}
}
}
});
app.engine('handlebars', handlebars.engine);
app.set('view engine', 'handlebars');
Any ideas what I’m doing wrong here or how to add support for both sections?
Thanks
I think your sections are overwriting each other. Try changing your handlebars create to the following:
var handlebars = require('express3-handlebars')
.create({
defaultLayout: 'main',
helpers: {
section: function (name, options) {
if (!this._sections) {
this._sections = {};
}
this._sections[name] = options.fn(this);
return null;
}
}
});

hide iframe url in HTML source code

How to hide iframe url From HTML source code?
<iframe src="http://mysite.com" frameborder="0" scrolling="no" width="728" height="90"></iframe>
You can use javascript to load the source, and it will not be visible in iframe url in page source code.
For example with jQuery:
<script type="text/javascript">
$(document).ready(function(e) {
$('iframe').attr('src','http://www.flickr.com/');
});
</script>
<body>
<iframe src="" />
</body>
Example here.
You can combine it with $.post to get the value serverside:
$.post('get-iframe-src.php', function(data) {
$('iframe').attr('src',data);
});
You can even load iframe itself to some element like:
$.post('get-iframe.php', function(data) {
$('#element_id').html(data);
});
etc. solutions are many, this is just one of.
You can't. If the URL isn't in the HTML, how would the browser know where to get it?
One thing you could try is to obscure it to make it slightly harder for someone to find it. You could have the src attribute be blank and then when the document is ready fetch the URL value from the server in a separate AJAX request and update the iframe tag to include that value in the src.
This would be a fair amount of work, however, and wouldn't really accomplish anything. The only thing it would prevent is somebody finding it by viewing the page source. They can still look at the "current version" of the HTML in any web browser's debugging tools. (Right click on an element and inspect it, which is nearly ubiquitous at this point.) Or any other normal traffic-sniffing tools will see it plain as day.
Ultimately, if the web browser needs to know a piece of information, then that information needs to be visible on the client-side.
There's no way to fully block source viewing. But there are a couple ways to disable right-clicking:
1) Javascript:
<script language="JavaScript">
<!--
var message="Your message goes here.";
function click(e) {
if (document.all) {
if (event.button == 2) {
alert(message);
return false;
}
}
if (document.layers) {
if (e.which == 3) {
alert(message);
return false;
}
}
}
if (document.layers) {
document.captureEvents(Event.MOUSEDOWN);
}
document.onmousedown=click;
// -->
2) Add the following into your tag: oncontextmenu="return false"
reference https://forum.powweb.com/archive/index.php/t-36161.html
I decided for solution that does not use javascript, because most of the time it will be possible to read the "hidden" content.
Moreover, changing iframe SRC with javascript, will keep URL hidden when checking the source. However, inspecting the code will show the real URL.
My code is in PHP; however, I believe that the logic can be translated to other programming languages. This is how it works:
I kept the iframe tag as usual:
<iframe src="dash_url.php"></iframe>
The trick is inside the iframe_url.php, where I validate the referer. If it is valid, page is redirected to iframe URL. If it is not, than URL will be a message.
<?
$iframe_url = "https://example.com";
$Referer = #$_SERVER["HTTP_REFERER"];
$RefererHost = #explode(":", explode("/", explode("//", $Referer)[1])[0])[0];
if ($RefererHost == $_SERVER["SERVER_NAME"]) {
header("Location: " . $iframe_url);
} else {
echo "Invalid URL";
}
?>
If visitor inspects the page or checks the source, iframe tag will show SRC as dash_url.php.

Resources