In Jade you can pass through an object to the client like this
Route:
res.render('mypage', {
title: 'My Page',
myobject : data
});
Jade Template:
extends layout
block navbar
include includes/navbar
block top
include includes/top
block content
script(src='/js/controllers/test-controller.js')
script.
var clientobj = !{JSON.stringify(myobject)}
But what if myobject does not exist? It seems like it would be the simplest thing to check if this object exists before using it (and therefore only try to define the var clientobj if it does) but I am banging my head here trying to get make this happen.
Eg:
res.render('mypage', {
title: 'My Page'
});
Will currently break the given template, there has to be some syntax to make this code more resilient, surely..
The following code snippet should help.
script
if myobject
| var clientobj = !{JSON.stringify(myobject)}
Please note that you should not put . (dot) at the end of script element. Otherwise if myobject ... will be considered as text and not Jade code.
Alternatively this should work too:
script.
var clientid = #{myobject ? JSON.stringify(myobject) : "undefined"};
In that case you will get following HTML code and you will have to handle clientid as undefined in your JavaScrip code in a page.
<script>var clientid = undefined;</script>
I hope that will help
Related
Following is a pug snippet. I need to dynamically populate the user in chatConfig object.
script.
var chatConfig = {
user : 'foo',
pass : 'bar',
}
From my express , I am rendering as
resp.render('user/index', {username:req.user});
How do I pass the value of req.user to user key inside script.?
Brmmmm is on the right track, but you need to get your JavaScript to use the variable as an object, not as a variable. You can stringify the variable to get it to work as a JavaScript object.
doctype html
html(lang='en')
head
title Jade
- var test = {prop1: "Hi there", prop2: "Another test"};
script(type='text/javascript').
var test2 = !{JSON.stringify(test)};
console.log(test2, test2.prop1, typeof test2);
body
h1 Jade - template engine
#container.col
p I'm some Jade
Live Example; check the browser console/Codepen console to see what the console.log statements output.
I think it should look like this:
script.
var chatConfig = {
user : '${username}',
pass : 'bar',
}
I'm just starting with Flask, so I may be overlooking something very obvious. I have loaded my javscript file with this:
<script src="{{ url_for('static', filename='Page.js') }}"></script>
then I try to instantiate an object from that js file:
<script>
var page = new Page("index");
</script>
In Page.js, I have this:
var Page = function(page) {
alert("init");
<some other things>
}
<and then some object methods Page.prototype.init_standard = function() {} etc>
The alert isn't alerting, though I am expecting it to. Also, if I put an alert before the instantiation in the HTML page, I get the alert, if I put an alert on the line after the instantiation on the HTML page, I don't get the alert. I'm not sure if this is a Flask issue or javascript -- I'm quite new at both.
EDIT: To nip this possibility in the bud, the javascript file is getting loaded according to the development server, status 304
Page.js needs to just define a function that creates the object you want. So Page() should just be a function that ends with 'return this;'. Correction returning this is not strictly required for object creation.
function Page(page) {
alert("init");
... Your code and methods...
// Example Method:
this.foo = function(param) {
... function body ...
};
return this;
}
And then you can create an object with:
var page_object = new Page("index");
page_object.foo(some_data);
I figured it out after looking at the browser debugger. It said Page was not defined. After some trial and error, I realized I can't use {{ flask templating notation inside the javascript file, probably because it isn't loaded as a template so no parsing of it in that way occurs. Anyway, I ended up just moving the {{ }} link to the html template and passing it in as an argument to the javascript.
How do I get reference of the <div> id and title from a external JS by using the code below:
function recordedEvent() {
var v_Id = $(this).attr('Id');
var v_Title = $(this).attr('Title');
var o = { Title : v_Title, ObjectId : v_Id };
alert(JSON.stringify(o));
}
The function is called in the HTML with a onclick called box1().
Code in CplTemplateSetup.js is where I want to run the function from into the HTML:
content_left_30_four_click_images_right_70_head_content_template.html
Any help would be appreciated.
P.S.: JSON data (zip archive)
Well the most obvious problem is that you don't have a closing parenthesis after your callback.. otherwise the code looks good
Edit
window.lastClickedBoxData = {}; // just reassign that within your function
or
window.runThisWhenClicked = function () {
var v_Id = $(this).attr('Id');
var v_Title = $(this).attr('Title');
var o = { Title : v_Title, ObjectId : v_Id };
};
then just
$(".box").click(window.runThisWhenClicked);
I don't think that the problem that you're facing would be apparent to anyone who doesn't view your code.
You defined a function within a script tag, in the html, and called that function in the onclick attribute of the box being clicked on. To that function, this refers to the box that was clicked on. From there, you call a function within an external js document. In that function, this refers to the window object. In other words, for the code that you posted, $(this) is a jquery instance of the window object which doesn't have the attributes that you're looking for, such as id and title, so they're blank.
To see what I'm talking about open the console and add the following line of code to each of your functions:
console.log(this);
If you're having trouble doing that, the following code should work as well, but it's not as good for debugging:
alert(this);
You need all of your code to be in the html script tag or in the external document. Also, you shouldn't define the function to be called during a click event using onclick within the html. It's better to do it using javascript or jquery so that your javascript is completely separate from your html.
EDIT: You shouldn't update your question with an answer. You should edit the original question with this information so that anyone having a similar problem can find the solution. I'd have commented on the answer directly, but I don't have the reputation to do this.
Sorry I couldn't be anymore specific with the title.
I'm building a web-site (personal), which displays different content to the user depending on the query string that is used in the url.
e.g. page=home.html would display home.html
The websites Javascript is wrapped inside an object, with each value containing different data, some pseudo code:
(function(){
var wrapper = {
init: function(){
//Runs on document ready
this.foo();
this.nav.render();
},
foo: function(){
//Some functionality goes here for the website, e.g. Display something from an API
},
nav: {
//Functionality to handle the navigation, has different properties
config: {
//Contains the config for nav, e.g. page names + locations
dir: '/directory/to/content/',
pages: {
page_name: wrapper.nav.config.dir + 'page_value'
}
},
render: function(){
//some code
},
routes: function(){
//some code}
}
}
};
$(function(){
wrapper.init();
});
})();
My problem is that I'm trying to prepend the dir value to each of the page values (inside the object where the pages are defined), expecting to get the output of (in this pseudo code case) of directory/to/content/page_value, but instead dir is undefined when I'm trying to access it, I've tried the following to achieve what I want:
wrapper.nav.config.dir + 'page_value'
I've been playing around with the last 30 minutes trying to find out what I'm doing wrong, and even thought about hard-coding the URL in for each page.
The reasoning for wanting to do this is that my local development server and web host have different directory structures, so I don't want to re-write the URL's each time I want to develop + publish. As for why everything is wrapped inside an object, I thought it would be easier to maintain this way.
Hopefully the answer is simple and it's just an amateur mistake / lack of understanding.
The issue is that you can't refer to a variable that is being defined in that very definition.
So, inside the definition of wrapper, you can't refer to wrapper. And, inside the definition of config, you can't refer to config either and so on.
The usual design pattern for solving this is to initialize as much as you can in the declaration of your data structure and then do the rest in .init() when you can freely access all of it.
Change the first two lines to:
var wrapper = null;
(function(){
wrapper = {
Otherwise, the wrapper is a local variable to your anonymous function.
The problem is that you're still busy defining the wrapper when you ask for its value, which is why it's still undefined.
The code below fails too:
var x = {
y:"1",
z:x.y
}
Why not:
//...
init: function(){
//Runs on document ready
this.foo();
var config = this.nav.config;
for (var page in config.pages) {
config.pages[page] = config.dir + config.pages[page];
}
},
//...
I am writing a simple counter, and I would like to make installation of this counter very simple for users. One of the simplest counter code (for users who install it) I ever see was Google Analytics Code
So I would like to store main code in a file and user who will install my counter will need just to set websiteID like this:
<html><head><title></title></head><body>
<script type="text/javascript" src="http://counterhost.lan/tm.js">
var websiteId = 'XXXXX';
</script>
</body></html>
Here is my code:
<script type="text/javascript" src="http://counterhost.lan/tm.js">
var page = _gat.init('new');
</script>
and this is my JS file:
(function() {
var z = '_gat';
var aa = function init(data) { alert(data); alert(z);};
function na() {
return new z.aa();
}
na();
})();
I tried to understand Google Analytics javascript code but I failed to do this. Can anyone suggest how can I specify variable between tags and then read it in anonymous function which is located in a javascript file ?
Thanks.
In your example, websiteId is a global variable. So it is accessible everywhere including anonymous functions unless there is a local variable with the same name
<script> var websiteId = "something"; </script>
Later in the page or included js file...
(function() {
alert(websiteId); //this should work
})();
Can anyone suggest how can I specify variable between tags and then read it [...]
Not if your tag has both a SRC attribute and JS content.
<script type="text/javascript" src="http:/x.com/x.js"></script>
.. is different from,
<script type="text/javascript">
var x = 1;
</script>
One framework that optionally adds JS variables to SCRIPT tags is Dojo. So if you're using Dojo you can add variables to the global djConfig hash by writing,
<script type="text/javascript" src="mxclientsystem/dojo/dojo.js"
djConfig="
usePlainJson: true,
parseOnLoad: true
">
</script>
Dojo does this by running through the SCRIPT tags and evaluating the custom djConfig attribute.
This does not, however solve your problem.
You do really want two SCRIPT tags. One saying,
<script type="text/javascript">
var websiteId = '123456';
</script>
which will set a global variable websiteId and a second one,
<script type="text/javascript" src="http:/x.com/myreporter.js"></script>
which can load from anywhere and read out the websiteId variable and, I assume, report it back.
You can pass variables to an anonymous function like so:
(function(arg1, arg2, arg3) {
alert(arg1);
alert(arg2);
alert(arg3);
})("let's", "go", "redsox");
// will alert "let's", then "go", then "redsox" :)
I'm not entirely clear about what you're asking, but...
You can tag any HTML element with an id attribute, then use
document.getEntityById() to retrieve that specific element.
You can also give any HTML element user-defined attributes having names of your own choosing, then get and set them for that element within Javascript.
I think you've got a bit confused with how JS objects are called.
z is a String, '_gat'. You can't call aa() on it because a String has no member called aa. aa is a standalone function stored in a local variable. Even if you did call aa(), it doesn't return anything, so using the new operator on its results is meaningless. new can only be called on constructor-functions.
I guess you mean something like:
var _gat= function() {
// Private variable
//
var data= null;
// Object to put in window._gat
//
return {
// Set the private variable
//
init: function(d) {
data= d;
}
};
}();
Then calling _gat.init('foo') as in your second example would set the variable to website ID 'foo'. This works because the _gat object is the return {init: function() {...}} object defined inside the anonymous function, keeping a reference (a ‘closure’) on the hidden data variable.
If you specify a src attribute as part of a script element, any code within the script element tags themselves will not be executed. However, you can add this functionality with the following code. I got this technique from Crockford (I believe it was him), where he uses it in of his talks on the unrelated topic of rendering performance and asynchronously loading scripts into a page to that end.
JavaScript:
(function() {
// Using inner class example from bobince's answer
var _gat = (function() {
var data= null;
return {
init: function(d) {
console.info("Configuration data: ", d);
data = d;
}
}
})();
// Method 1: Extract configuration by ID (SEE FOOT NOTE)
var config = document.getElementById("my-counter-apps-unique-and-long-to-avoid-collision-id").innerHTML;
// Method 2: search all script tags for the script with the expected name
var scripts = document.getElementsByTagName("script");
for ( var i=0, l=scripts.length; i<l; ++i ) {
if ( scripts[i].src = "some-script.js" ) {
config = scripts[i].innerHTML;
break;
}
}
_gat.init( eval("(" +config+ ")") );
})();
HTML:
<script type="text/javascript" src="some-script.js" id="my-counter-apps-unique-and-long-to-avoid-collision-id">
{some: "foo", config: "bar", settings: 123}
</script>
Both methods have their draw backs:
Using a unique and non-colliding ID will make determining the proper script element more precise and faster; however, this is not valid HTML4/XHTML markup. In HTML5, you can define arbitrary attributes, so it wont be an issue at that time
This method is valid HTML markup; however, the simple comparison that I have shown can be easily broken if your url is subject to change (e.g.: http vs https) and a more robust comparison method may be in order
A note on eval
Both methods make use of eval. The typical mantra concerning this feature is that "eval is evil." However, that goes with say that using eval without knowing the dangers of eval is evil.
In this case, AFAIK, the data contained within the script tags is not subject to inject attack since the eval'ing script (the code shown) is executed as soon as that element is reached when parsing the HTML into the DOM. Scripts that may have been defined previously are unable to access the data contained within the counter's script tags as that node does not exist in the DOM tree at the point when they are executed.
It may be the case that a well timed setTimeout executed from a previously included script may be able to run at the time between the counter's script's inclusion and the time of the eval; however, this may or may not be the case, and if possible, may not be so consistently depending on CPU load, etc.
Moral of the story, if you're worried about it, include a non-eval'ing JSON parser and use that instead.