I have a Razor Class Library project in which I want to add a couple of custom components that use JavaScript interops. The interops work fine when I call functions that already exist in the Window object.
This, for example, works fine:
JSRuntime.InvokeVoidAsync("alert", "Hello world");
However when the functions I need are not native to the Window object, i.e. they are declared in a distinct interops.js file, I need to add a <script> tag referencing the said file in the page HTML. What is the path to that file since it resides in a different assembly?
There are two ways to approach this.
Consume static assets from a referenced RCL
From documentation
The files included in the wwwroot folder of the RCL are exposed to either the RCL or the consuming app under the prefix _content/{LIBRARY NAME}/. For example, a library named Razor.Class.Lib results in a path to static content at _content/Razor.Class.Lib/. When producing a NuGet package and the assembly name isn't the same as the package ID, use the package ID for {LIBRARY NAME}.
Read embedded asset contents using Reflection
This approach lets you execute Javascript code directly without need to include files in the HTML with <script>.
First create helper method to retrieve embedded javascript file contents:
public static string GetEmbeddedJSInteropCode(Assembly assembly, string path)
{
using var stream = assembly.GetManifestResourceStream(path);
using var reader = new StreamReader(stream);
return reader.ReadToEnd();
}
Then you can call it like this
await JSRuntime.InvokeVoidAsync("eval", GetEmbeddedJSInteropCode(typeof(SomeRCLType).Assembly, "SomeRCL.SomeFolder.Init.js"));
await JSRuntime.InvokeVoidAsync("someRCLFunction", "Foobar");
When the Razor Class Assembly is referenced in a Blazor Web Assembly project, the content of the Razor wwwroot/ folder is copied in the Blazor _content/*namespace*/ folder. So the solution is to move the .js file in the wwwroot/ and reference it in the script tag like this:
<script src="_content/*assembly_name*/file.js"></script>
Related
I have redefined this question from the original a bit to make it more fundamental to the question at hand. The relevant parts of my filesystem are as follows.
env
tutorial
tutorial
templates
view.pt
static
myjava.js
views.py
__init__.py
Right now my view.pt template has
<script type="text/javascript" src="/static/myjava.js"></script>
Then in my __init__.py, I have
config.add_static_view(name='static',path='env/tutorial/tutorial/static')
And finally, the myjava.js file itself is very simple:
document.write("hello from the javascript file")
I am trying to follow this document: http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/assets.html
but right now none of the text is showing up. I feel like the problem lies in the paths i am giving it.
Some ideas I have had: in the config.add_static_view, the name='static' is confusing. I want users to be able to visit the url www.domain.com/firstpage, where firstpage is the result of a template that uses a javascript file resource (a file in the static folder). I am worried that these static assets are only for urls that start with www.domain.com/static/... Is this a valid concern? How can I tell the config.add_static_view function to serve the static resources for any views rendered from the view.pt template?
Edit: here is what worked:
in the template, use src="${request.static_url('tutorial:static/myjava.js')}"
then in the init.py use config.add_static_view(name='static',path='tutorial:static/')
Your javascript link, in the template, should be something like src="${request.static_url('tutorial:static/myjava.js')}"
This allows your application to be more easily relocated.
This also uses the appropriate asset specification, using the name of the package,
"tutorial", a colon, then a path relative to the location of the "tutorial" package, which in your case the package is at env/tutorial/tutorial.
Edited: I forgot about the Configurator object.
Here, you want to use a similar asset specification such as config.add_static_view('static', 'tutorial:static/').
You can make different static views for different directories as well, like: config.add_static_view('images', 'tutorial:images/')
When you do things like this, you can move the root of your application to another location, allowing you to have http://mysite.com/stable/ and http://mysite.com/devel/ having accesses to / be rewritten to /stable/.
The static views can be called from any template with code like ${request.static_url('tutorial:images/icons/favicon.ico')}
Was reading the docs here and it looks like when you call add_static_view it changes the path of the file? To quote the docs:
this means that you wish to serve the files that live in /var/www/static as sub-URLs of the /static URL prefix. Therefore, the file /var/www/static/foo.css will be returned when the user visits your application’s URL /static/foo.css.
In your case, since you're calling env/tutorial/tutorial/static "static", you might want to try src="static/Three.js"> instead
In trying to keep with unobtrusive JavaScript guidelines I moved all the JavaScript out of each of my views and into a separate .js files.
However, within 1 view I need to dynamically create some JavaScript variables so these are inserted into the ViewBag and rendered directly into the view:
$(document).ready(function () {
#(ViewBag.PrePop)
#(ViewBag.PreDiscount)
});
This works fine until I had a go at using the new ASP.net bundling and minification feature.
Bundling all these small external JavaScript files together and then calling the combined script from every page means that every page (other than the one that contains the ViewBag emitted variables) has a variable reference error:
Uncaught ReferenceError: quotes is not defined
So this basically means I can't bundle this particular JavaScript file.
However, I would like to minify it. To do this, do I just declare a bundle that only contains the one JavaScript file:
bundles.Add(new ScriptBundle("~/bundles/mypagescript").Include(
"~/Scripts/mypagescript.js"));
Or is there another way to perform solely minification?
Yep, currently we don't really expose any methods for you to easily call in to Optimization just to minify a string (you could do it via an instance of JsMinify.Process if you really wanted) i.e.:
string js = "//I am a comment\r\nfoo = bar;\r\nfoo = yes;";
JsMinify jsmin = new JsMinify();
BundleContext context = new BundleContext();
BundleResponse response = new BundleResponse(js, null);
response.Content = js;
jsmin.Process(context, response);
Assert.AreEqual("foo=bar,foo=yes", response.Content);
But what you suggest is probably best (create a bundle of one file).
Sorry for the late answer ;)
You can use Microsoft.Ajax.Utilities.Minifier. Create an instance and call MinifyJavaScript - which takes a string (the JS-code) as a parameter and returns the minified code.
Dim minifier As New Microsoft.Ajax.Utilities.Minifier()
minifier.MinifyJavaScript(script)
You could then create your own HTML-helper or action to call for this. This worked well in my case atleast ;)
I was trying to convince a fellow co-worker into using Mustache/Hogan in the front-end of a project and I proposed the following:
Having a templates.js file, which could roughly look like this:
var tpl_alert = '<div class="alert">{{msg}}</div>';
var tpl_welcome = '<p class="user-{{type}}">Welcome, {{name}}</p>';
...
Then, we would include templates.js and use the corresponding tpl in the Mustache/Hogan.js rendering.
My proposal was turned down, since we're hardcoding html templates into js variables.
Is this really that bad? Which are other alternatives to this?
To answer your question, putting your templates in javascript variables inside a static JavaScript file makes it difficult to maintain your templates. You need to worry about string escaping whenever you want to make a simple change. And 1 syntax error will crash your app.
However, putting all your templates in a single JavaScript file is the fastest way to load your templates.
Your alternatives are:
Storing your templates in seperate files and generating the static template.js file as a prebuild step.
Loading your html template files async through AJAX into javascript variables.
Using a library like Require.js that will load your templates asynchronously as needed into variables.
My preferred way of doing this is to create a separate template file that can be loaded dynamically in development and baked into pure js for production.
Specifically I use eco templates (I wouldn't recommend them unless you're familiar with coffee script) and Stitch for node.js. Stitch supports custom engines tied to file extensions, so when it finds an eco file in my project directory it compiles it into a Javascript function. I can now include that function in any other part of my application using the stitch provided require function using the original path of the eco file. So if the template resided in src/views/listItem.eco I would run var listItemView = require('views/listItem'); to fetch it and use it like this
var html = listItemView({item: items[i]});
$someElement.html(html);
You could use require.js instead of stitch if course, or any other similar framework.
I am trying to create a Silverlight class library which needs to call a few Javascript methods. I have put these methods in a single .js file and have added it to the project. But when I try to call any of the methods in the js file, I get a FailedtoInvoke error. I understand that this problem can be solved by adding a reference of the JS file in the head section of ASPX or HTML page. But I am developing a class library and so that is not possible. Does someone know how to tackle this issue? I am using Silverlight 4 and Visual Studio 2010.
Add the .js file to your library probject as it sounds you have done, make sure it Build Action is "Resource".
You can retrieve this content with Application.GetResourceStream :-
StreamResourceInfo sriJS = Application.GetResourceStream(new Uri("YourAssemblyName;component/MyStuff.js", UriKind.Relative));
Note the structure of the Uri, the assembly name of your class library is needed followed by the literal ";component". This tells Silverlight to look for a resource inside your dll that will be included in a final application's Xap.
Now you need to turn the content of the info's Stream property into a string:-
StreamReader reader = new StreamReader(sriJS.Stream, System.Text.Encoding.UTF8);
string js = reader.ReadToEnd();
Finally you can inject that javascript into the current page with:-
HtmlPage.Window.Eval(js);
Thats it, any global functions defined in the js may now be invoked with HtmlPage.Window.Invoke.
Try something like:
string myScriptCodeString = GetScriptCodeStringFromSomewhere();
System.Windows.Browser.HtmlPage.Window.Eval(myScriptCodeString);
Then the methods defined in myScriptCodeString should be available.
I am newby in Spring, but have a task, and I am learning on the fly.
I used Roo to generates for me part of the code, but now I have to make some dynamic list binding, which is done with form, popping-up in new window, and when the submit button is pushed I have to insert the new values in the parent window.
For the purpose I wrote a .js file, which hooks the values to the parent DOM tree, but the point is that I can't configure Spring to deliver the required .js file to the browser.
The browser, doesn't recognize my function. Even when I try to access the .js file via the browser, I receive error that the file couldn't not be found.
I've tried to configure the web.xml, but it didn't work...
Any ideas, how I can configure the access to a .js file in a Spring MVC application?
Thanks a lot!
P.S. Respectively, I'll need to grant access for a static .htm(l) file... I suppose the principle for configuration of the access of static html files is the same..., right?
You just need to get the path to the file right. Assuming you have a Maven-like set-up (I assume you do because you're using Roo), then your script belongs under src/main/webapp - probably in something like a scripts folder.
Let's assume that your file is at src/main/webapp/scripts/myscript.js
You can create a URL reference for your script by adding the following Spring tag:
<spring:url value="/scripts/myscript.js" var="script_url"/>
This should give you the right path to your script, regardless of the context in which you later decide to publish your webapp.
After that, it's just a matter of using that reference:
<script type="text/javascript" src="${script_url}"></script>