I have an external report.html file which contain also JavaScript.
This JavaScript has a lot of variables which contain a lot of values. (Mb in plain text)
At the end is taken and render to the nice table. But I need take this variables out from the report.html to the Node-red and process them there.
I tried to load the file and print it out by but it did not do the JavaScript function inside.
Do I have somehow read the variable as an variable in node-red?
Of course I could do the parser and process through whole document and parse it manually but it is tuns of work in case it is possible to just load it somehow.
Given that your html is already loaded as string in msg.payload and your javascript code is bounded by <script> and </script> tags, you can first parse your html by:
var jsCode = msg.payload.split("<script>").pop().split("</script>")[0];
And then to run the code represented in jsCode string use eval() function:
eval(jsCode);
Your environment will act as it was written in editor and executed by you, so you should have access to all vars and functions declared in the inline js code.
Disclaimer
Actually it is not safe to use eval() SEE WHY, but for your case maybe it's the best solution.
Related
So I'm working on my first webapp in visual studio and I'm having a problem.
In my HTML file I want to declare a variable that I can use in my javascript file, but I do not know how.
I know the basics of html, but I don't know much javascript (but I need to use it).
Is there a way I can declare a variable in my html script and use the same variable with the same given value in an other javascript file
So the variable needs to be used in API.js and registreerPagina.csHTML
Thanks in advance for helping me!!
The simplest way is just to put a tag in your HTML. This will just inject the javascript into your page.
<script>var msg = "Hello world";</script>
But because Javascript is a script, you need to be sure that your tag is rendered before your javascript file tries to use it. That's a bit more of a complex subject, but this is the basic idea if you just want to declare a variable.
Regardless of the server-side structure, the resulting client-side is ultimately just one "page" in the browser and any JavaScript on or referenced by that page is executed by the browser. So in that page you can do something like this:
<script type="text/javascript">
var x = 'some value';
</script>
<script type="text/javascript" src="someFile.js"></script>
If there's code in someFile.js which references a window-level variable called x then that variable will at that time have the value 'some value'. All of the JavaScript loaded, whether on the page or references in a separate file, will be executed in the order it's loaded and all under the same window context.
In structures such as ASP.NET this can be useful when a value is dynamic in the view and needs to be used in the JavaScript, which sounds like the situation you're experiencing. Suppose you design your JavaScript file such that it gets loaded and then needs to be invoked with some injected values. You can have something like this:
<script type="text/javascript" src="someFile.js"></script>
<!-- lots of page content, then at the bottom... -->
<script type="text/javascript">
var x = '#someServerSideValue';
invokeJS(x);
</script>
In this case there could be lots of code within someFile.js, but it's all just defined and not actually executed yet. Its execution is wrapped in a function to be invoked when the page finishes loading. (In this case that function is called invokeJS.) That function expects a parameter (or multiple parameters) to provide it with values needed by that code, much like dependency injection.
So, there are a couple of ways you could approach this. The first method would be to create an API controller in your application and call the endpoint to return your value/values:
// Assuming you have referenced jQuery
$(function() {
$.getJSON("/api/schweetvariable", function(data) {
localVar = data;
});
});
The other way would be to generate the JS file from the server side via a httphandler or similar. Honestly, I'd go the API route as its pretty straightforward and easy to implement and maintain.
There are a few other ways you could achieve this: SignalR with a persistent connection or inline your API.js logic if that's an option.
There's some good reasons to avoid the eval() function in JavaScript, namely security risks when including user input in the eval() code. However, in a situation where the eval() code does not include anything affected by user input (in my particular situation, we have dynamic templates defined in XML files - these templates can also specify complex validation functions, javascript code that is embedded in the XML, which is then received by the client via AJAX), is there any reason to avoid the eval() function?
I came up (I'm probably not the first, but I haven't seen this done) with a solution using a dynamically created inline tag instead of eval():
$(scriptObject).text(strJSCode);
A simple example can be seen at http://jsfiddle.net/H7EG9/1/ (I know this example does use user input, but that's just to make it easy to demonstrate).
Is there any reason to do this instead of eval()? The outcome is basically the same, although this option might appear less "scary" to the die-hard foes of eval().
I would use eval instead of creating script tags.
Script tags create overhead (they are DOM elements) but more importantly, you will need to use some sort of global variable to access the script in the script tags. If you use eval, you can simply do
var evalFunction = eval("(function(){...})"); // wrap function in () to make it an expression
var result = evalFunction(val);
IE8 and below do not allow scripts to be served in data: format. In that regard, eval() is more reliable.
That being said, if you are using AJAX to download a JS file from which you are getting that string, you could just set scriptObject.src = 'path/to/script.js'; The browser will have the file in cache and will therefore load it immediately.
eval is easy to write, but it is nearly as easy to add a script element to the head or body and append the js text to the new script element. Some edge cases, like variable hoisting, behave a little oddly when evaling a script.
It is possible to obtain as a string the content of an external script? Something equivalent to myInlineScript.textContent?
The scenario is that I'm just starting to get into WebGL and all the tutorials I'm finding store shaders as inline <script type="x-shader/x-foo"> tags. The element itself isn't important, however — the shaders are created from plain strings. These are easily extracted from inline scripts via .textContent, but I'd of course prefer to keep my code separate from my markup.
Is there some equivalent for getting the source / content of an external script? A quick scan of the DOM docs and a Google search didn't yield anything enlightening.
Update
The WebGL shaders aren't a huge problem — there are a number of ways of getting strings in Javascript! But this isn't the only time I've encountered script tags being used to inline non-scripts and it got be curious about a better way to do it.
If it's on the same domain you can just do a normal ajax request for it, and get the file back as a string. This works for any kind of text file.
Also, I am not familiar with WebGL, but if your shaders are in external files then I assume the "x-shader" script type is simply a way to put them inline. Otherwise, it's just a string you pass to a method somewhere. So don't over-think this too much.
I'm developing a facebook app right now all by my lonesome. I'm attempting to make a javascript call on an onclick event. In this onclick event, I'm populating some arguments (from the server side in php) based on that item that is being linked. I'm inserting a little bit of JSON and some other stuff with funky characters.
Facebook expects all the attribute fields of an anchor to be strictly alphanumeric. No quotes, exclamation marks, anything other than 0-9a-Z_. So it barfs on the arguments I want to pass to my javascript function (such as JSON) when the user clicks that link.
So I thought, why don't I use my templating system to just autogenerate the javascript? For each link I want to generate, I generate a unique javascript function (DoItX where X is a unique integer for this page). Then instead of trying to pass arguments to my javascript function via onclick, I will insert my arguments as local variables for DoX. On link "X" I just say onclick="DoX()".
So I did this and viola it works! (it also helps me avoid the quote escaping hell I was in earlier). But I feel icky.
My question is, am I nuts? Is there an easier way to do this? I understand the implications that somehow somebody was able to change my templated local variable, ie:
var local = {TEMPLATED FIELD};
into something with a semicolon, inserting arbitrary javascript to the client. (and I'm trying to write code to be paranoid of this).
When is it ok (is it ever ok) to generate javascript from the server? Anything I should look out for/best practices?
Depending on your application generating JavaScript in your templating language can save a lot of time but there are pitfalls to watch out for. The most serious one being that it gets really hard to test your JavaScript when you don't have your full templating stack available.
One other major pitfall is that it becomes tempting to try and 'abstract' JavaScript logic to some higher level classes. Usually this is a sign that you will be shaving yaks in your project. Keep JavaScript login in JavaScript.
Judging from the little bit of information you have given it your solution seems sensible.
If you must generate javascript, I would suggest only generating JSON and having all functions be static.
It more cleanly separates the data, and it also makes it easier to validate to prevent XSS and the like.
JS generated from server is used in lots of areas. The following is the sample from a ASP.NET page where the JS script is generated by the framework:
<script src="/WebResource.axd?d=9h5pvXGekfRWNS1g8hPVOQ2&t=633794516691875000" type="text/javascript"></script>
Try to have reusable script functions that don't require regeneration; and 'squeeze' out the really dynamic ones for server-side generation.
If you want to feel better about it, make sure that most of your JavaScript is in separate library files that don't get generated, and then, when you generate code, generate calls to those libraries rather than generating extensive amounts of JavaScript code.
it's fine to generate JS from the server. just bear in mind not to fine too big a page from the server.
Generally speaking I avoid ever automatically generating JavaScript from a server-side language, though I do however; create JavaScript variables that are initialized from server-side variables that my JavaScript will use. This makes testing and debugging much simpler.
In your case I may create local variables like the following which is easy to test:
<script type='text/javascript' language='javascript'>
<!--
var FUNC_ARG_X = <%= keyX %>;
var FUNC_ARG_Y = <%= keyY %>;
var FUNC_ARG_Z = <%= keyZ %>;
//-->
</script>
<script type='text/javascript' language='javascript'>
<!--
function DoCleanCall(arg) {
// Whatever logic here.
}
//-->
</script>
now in your markup use:
<a href='#' onclick='DoCleanCall(FUNC_ARG_X);'>Test</a>
Now of course you could have embedded the server-side variable on the <a/> tag, however it is sometimes required that you refer to these values from other parts of your JavaScript.
Notice also how the generated content is in it's own <script> tag, this is deliberate as it prevents parsers from failing and telling you that you have invalid code for every reference you use it in (as does ASP.NET), it will still fail on that section only however.
There are essentially 2 places to define JavaScript functions in Grails, directly in a element on the GSP, and within a separate javascript source file under /web-app/js (for example, application.js). We have defined a commonly reused javascript function within application.js, but we also need to be able to generate parts of the function dynamically using groovy code. Unfortunately, ${some groovy code} does not appear to be processed within separate javascript source files.
Is the only way to do this by defining the javascript function within a script tag on a GSP page, or is there a more general solution? Obviously we could define the javascript function in a script tag within a template GSP file which would be reused, but there is a lot of push to keep our javascript functions defined all together in one place (i.e. the external javascript source file). This has performance benefits as well (the javascript source files are usually just downloaded once by each client's browser, instead of reloading the same javascript functions within the source of every html page they visit). I have toyed around with the idea of breaking the function up into static and dynamic pieces, putting the static ones in the external source and putting the dynamic ones in the template GSP, then gluing them together, but this seems like an unnecessary hack.
Any ideas?
(edit: It may sound like the idea of dynamically generating parts of a JavaScript function, which is then downloaded once and used over and over again by the client, would be a bad idea. However, the piece which is "dynamic" only changes perhaps once a week or month, and then only very slightly. Mostly we just want this piece generated off the database, even if only once, instead of hard coded.)
An easy solution to keep your JavaScript unobtrusive is to create a JavaScriptController and map its actions "/js/*" by adding this to your UrlMappings.groovy file:
"/js/$action"{
controller = "javascript"
}
then just create an action for each dynamic JS file you want, include in in your layout <HEAD>, and presto, you've got a JS file that you can insert Grails snippets into! :)
Note: I've found that there's currently a bug in Grails that doesn't map file extensions to content-types properly, so you'll need to include <%# page contentType="text/javascript; UTF-8" %> at the top of your view files.
This is a great solution. I would like to offer a suggestion to use somthing other then a mapping of "/js/$action" because this is no longer going to allow you to access you javascript files in /web-app/js/. All your javascript files would have to be moved to a the directory your controller would point to.
I would use something like
"/dynjs/$action"
This way you still can point to files in the /web-app/js/ files with out conflict and enjoy the benifits of gsp tags in javascript files
Please correct me if I'm wrong.
Or this... have a tag/service/dynamic method that lets tags write out their JS+CSS+whatever else, to a "cache" which is used to build the JS+CSS resources by a different controller.
Full concept here: [http://www.anyware.co.uk/2005/2009/01/19/an-idea-to-give-grails-tags-esp/][1]
If you want to use models created by the controller (that rendered HTML page which reference the Javascript in which you intend to use groovy code) in the Javascript code, then you can use this technique:
This technique does not need to change URL mappings and does not require you to create extra controller.
In your view GSP add javascript as follows:
<script type="text/javascript">
<g:render template="/javascript/yourJavascriptFile"/>
</script>
In views folder create a "javascript" folder. And create a file named:
_yourJavascriptFile.gsp
You can not only use all the GSP code in your _yourJavascriptFile.gsp file, but you can also use all the models created in your controller (that is rendering the view).
NOTE: There is nothing special about javascript folder. You can name it anything you want OR use an existing view folder. This is just a matter of organizing and identifying your HTML spitting GSP from Javascript spitting GSPs. Alternatively, you can use some naming conventions like: _something.js.gsp etc.
Name your scripts like this
/wherever/the/js/files/are/thescript.js.gsp
The gsp code inside will be rendered correctly by grails. This works, but I have no idea if it's considered a Good Idea or not.
There is another way - pass in the generated code into a function that expects closures. Those closures is generated by the program of course. The generated code is of course inlined/script-tagged in the gsp page.
it may or may not work depending on the nature of the code being generated. But i suspect it will work, and if it doesnt, minor tweaking to the coding style of your javascript will definitely make it work. Though, if these 'generated' code doesnt change much, this quite overkill imo.