JavaFX WebView load local Javascript file - webview

I am experimenting with the JavaFX WebView control and I want to use the MathJax Javascript library to render mathematical content.
As a test I have created a basic JavaFX FXML project, added a WebView to the FXML and updated the controller code like so:
public class SampleController implements Initializable {
#FXML
private WebView webView;
#Override
public void initialize(URL url, ResourceBundle rb) {
webView.getEngine().load(
"file:///Users/benjamin/Desktop/Page.html");
}
}
The html file looks like this:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/x-mathjax-config">
MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});
</script>
<script type="text/javascript"
src="/Users/benjamin/Downloads/mathjax/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
</head>
<body>
When $a \ne 0$, there are two solutions to \(ax^2 + bx + c = 0\) and they are
$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$
</body>
</html>
This works as expected and produces the following result:
Note that for the test, both the html and JavaScript file paths are hard coded to locations on my hard drive so the next step is to package the html as a resource that is bundled with the application so that it is not looking for local files.
I have updated the controller code to look up the page like this (the html has not been changed).
#Override
public void initialize(URL url, ResourceBundle rb) {
webView.getEngine().load(
this.getClass().getResource("Page.html").toExternalForm());
}
but this produces the following result:
As you can see, the mathematical content is no longer rendered.
If I change the html <script> tag to reference the JavaScript from a CDN, then everything works as in the original example but I would like to be able to reference the local JavaScript file (and eventually a version that is bundled with the application).
Is what I'm trying to achieve possible?

Add the MathJax.js file to the same package/folder of Page.html then reference to it as
<script type="text/javascript"
src="MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>

Related

why does .net core "Return" verb inside a controller adds "plaintext.css" ?

I was doing some testing with MVC6 .net core, and did a quick hack to return a bootstrap html code by putting dirtyHTML directly inside a controller.
The HTML contains the official example of bootstrap inside a literal string.
Just a quick way of returning some bootstrap html, (as i experiment with controller functionality), to my surprise when i go to a page using a web browser, all html text is shown like plain text, its not rendered.
namespace WebApplication1.Controllers
{
public class MariaController
{
[HttpGet("/index")]
public string index()
{
string dirtyHtml;
dirtyHtml =
#"<!DOCTYPE html>
<html lang=""en"">
<head>
<title>Bootstrap Example</title>
<meta charset=""utf-8"">
<meta name=""viewport"" content=""width=device-width, initial-scale=1"">
<link rel=""stylesheet"" href=""https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"">
<script src=""https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js""></script>
<script src=""https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js""></script>
</head>
<body>
<div class=""container"">
<h1>My First Bootstrap Page</h1>
";
return dirtyHtml;
}
}
When going to debug mode, initially they show the same asci text, but using firefox i see there is a line inserted before my page code:
<HTML><head>
<link rel="alternate stylesheet" type="text/css"
href="resource://gre-resources/plaintext.css"
title="Wrap Long Lines">`
So then i thought, let's look around in the solution and search for "Wrap Long Lines".. as to see where it comes from,... this is however not found.
So where does that come from ? (as the solution doesnt contain plaintext.css either). And more important to me, can it be disabled?.
I am not sure what you want to achive but following thing is way to go.
"Wrap Long Lines" and css related to that are internal to firefox browser.
You are saying that you return html and it display like html but it does not render html and for that do following thing.
[HttpGet("/index")]
public IActionResult index()
{
string dirtyHtml;
dirtyHtml =
#"<!DOCTYPE html>
<html lang=""en"">
<head>
<title>Bootstrap Example</title>
<meta charset=""utf-8"">
<meta name=""viewport"" content=""width=device-width, initial-scale=1"">
<link rel=""stylesheet"" href=""https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"">
<script src=""https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js""></script>
<script src=""https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js""></script>
</head>
<body>
<div class=""container"">
<h1>My First Bootstrap Page</h1>
";
return Content(dirtyHtml,"text/html");
}
See I have return IActionResult and Use Content from return.
Reason for this is when you return string it will display as string and if it is html then it will become encoded as you did not tell browser content type so it consider "text/plain".
An alternative of #dotnetstep's way is using Produces attribute:
[HttpGet("/index")]
[Produces("text/html")]
public string Index()
{
...
}

How to use html templates in electron framework?

I need to build a cross platform app with multiple windows. So I would like to know how to use html templates in electron.
Based on a similar question and what I've seen, there's no built in html template language in Electron, which is actually great because it allows you to use any other template language.
I'm currently playing with ejs in Electron.
Below is my index.ejs template file:
<html lang="en">
<head>
<title>The Index Page</title>
</head>
<body>
<h1>Welcome, this is the Index page.</h1>
<% if (user) { %>
<h3>Hello there <%= user.name %></h3>
<% } %>
</body>
</html>
And below is a section of my main.js file where the above template is rendered and loaded onto the BrowserWindow. Note that I've left out most of the boilerplate code:
const ejs = require('ejs');
//... Other code
let win = new BrowserWindow({width: 800, height: 600});
//... Other code
// send the data and options to the ejs template
let data = {user: {name: "Jeff"}};
let options = {root: __dirname};
ejs.renderFile('index.ejs', data, options, function (err, str) {
if (err) {
console.log(err);
}
// Load the rendered HTML to the BrowserWindow.
win.loadURL('data:text/html;charset=utf-8,' + encodeURI(str));
});
I'll give some credit to this gist for helping me find the data:text/html;charset=utf-8 part of the url that can be used to load dynamic content.
UPDATE
I'm actually not using this anymore. It's faster to just load the default html and use the native DOM methods. The Electron Quickstart program shows how to do this nicely.
Another option is to do the templating during your build. Here is a simple example using gulp to add nonces to the CSP meta tag and the inline script.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'nonce-<%= scriptNonce %>';">
<title>Basic Electron App</title>
</head>
<body>
<div id="app"></div>
<script type="application/javascript" nonce=<%= scriptNonce %>>
require('./index.js');
</script>
</body>
</html>
and in gulfile.js add the following to what you already have and make sure this task is included in your pipeline. You can also just update your current html task with the code below.
const template = require('gulp-template');
const uuidv4 = require('uuid/v4');
gulp.task('copy-html', () => {
// Create nonces during the build and pass them to the template for use with inline scripts and styles
const nonceData = {
scriptNonce: new Buffer(uuidv4()).toString('base64'),
styleNonce: new Buffer(uuidv4()).toString('base64')
};
return gulp.src('src/*.html')
.pipe(template(nonceData))
.pipe(gulp.dest('dist/'));
});
This is a very stripped down example. I have a more complete example at https://github.com/NFabrizio/data-entry-electron-app if anyone is interested, though there is still one warning when running the application because one of the packages I am using pulls in react-beautiful-dnd, which adds inline styles but does not currently accept nonces.

Using custom html when running unit test

I am trying to use a custom HTML page when running a unit test. I am following the instructions outlined on https://github.com/dart-lang/test#running-tests-with-custom-html
My test code (in file test/custom_html_test.dart) looks like
#TestOn( 'browser')
import 'dart:html';
import 'package:test/test.dart';
main( ){
test( "find select", (){
SelectElement selectAddTimezone = querySelector('#addNewTimezone');
expect( selectAddTimezone, isNotNull);
});
}
and the html page (in file test/custom_html_test.html) looks like
<!doctype html>
<!-- custom_html_test.html -->
<html>
<head>
<title>Custom HTML Test</title>
<link rel="x-dart-test" href="custom_html_test.dart">
<script src="packages/test/dart.js"></script>
</head>
<body>
<select id="selectAddTimezone"></select>
</body>
</html>
I use the following to run the test
pub run test -p dartium test\custom_html_test.dart
Dartium starts up and loads the page 'test Browser Host' to run the test - which fails due to the code not finding the selectAddTimezone element, not the custom html I provided.
I am sure I am missing something simple....
Richard
Just use the correct selector
SelectElement selectAddTimezone = querySelector('#addNewTimezone');
should be
SelectElement selectAddTimezone = querySelector('#selectAddTimezone');

How call jScript function in MVC view

I have this function in.js file:
function setValue(amount) {
if (amount === 0) {
.....
loanDriver._mem.loanValue = amount;
}
I like to call this in my MVC view and send this value to it : Model.ApprovedAmount
I tried this:
<script type="text/javascript">
setValue(#Html.Raw(Model.ApprovedAmount))
</script>
it is not working.
How I can do that?
Your existing code likely doesn't need the Html.Raw() call, but besides that it at least appears to be correct :
<script type="text/javascript">
setValue(#Model.ApprovedAmount)
</script>
There are a few things that you may want to look into to further troubleshoot this issue :
Check Your References
Firstly, make sure that the Javascript file that defines your setValue() function is being referenced prior to your existing <script> tag shown in your example. This is important as otherwise your page won't know what setValue()
is:
<script src='your-file-with-setvalue-defined.js'></script>
<script>
setValue(#Model.ApprovedAmount);
</script>
Use the Developer Tools
Check the Developer Tools (F12) within your browser, specifically the Network and Console tabs. These will reveal additional details about what exactly is going wrong (i.e. 404 errors, undefined functions, bad arguments, etc.).
Use the debugger
Consider using the debugger keyword within your setValue() function to see if it's being called and what the value that is being passed in looks like :
<script>
// Run this with your Developer Tools open and step into the function to
// see more
debugger;
setValue(#Model.ApprovedAmount);
</script>
Example
You can see a complete example here and seen below that demonstrates the basic idea behind this working as expected :
// HomeController.cs
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new SampleViewModel(){ Amount = 42 });
}
}
// SampleViewModel.cs
public class SampleViewModel
{
public int Amount { get; set; }
}
// Index.cshtml
#model HelloWorldMvcApp.SampleViewModel
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Calling Function From Model</title>
</head>
<body>
<script>
function setValue(amount) {
alert(amount);
}
setValue(#Model.Amount);
</script>
</body>
</html>
assuming you are just doing it on the view, you can do something like this:
<text><b>some text:</b> </text> #Html.TextBox("something", null, new { "callsomefunction"() })
Thanks guys, simply I had to use name of the file dot name of the function and it worked. jsfile.setValue(#Model.ApprovedAmount);

Loading a web component in Dart M2 (web_ui)

Through my journey of dart, I stumbled upon a "blocker" in terms of loading a component.
While having my component defined as followed:
<!DOCTYPE html>
<element name="x-foo" constructor="FooComponent" extends="button">
<template>
<button type="button" class="btn {{classes}}"> {{text}} </button>
</template>
<script type="application/dart">
import 'package:web_ui/web_ui.dart';
String classes = '';
String text = '';
class FooComponent extends WebComponent {
}
</script>
</element>
and referencing the component as followed:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>example</title>
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<!-- '../web/foo.html' or '../web/out/foo.html.dart' -->
<link rel="components" href='foo.html'>
</head>
<body>
<h1>example</h1>
<p>Hello world from Dart!</p>
<x-foo></x-foo>
<script type="application/dart">void main() { }</script>
<script type="text/javascript" src="dart.js"></script>
</body>
</html>
and my build script not creating a html file (output folder: foo.html.dart), I'm not sure to which file I have to reference.
The manual is also not declarative enough to solve my issue:
http://www.dartlang.org/articles/dart-web-components/spec.html#loading-components
Referencing to either the definition of the component (foo.html) or it's generated output (foo.html.dart) is not working. I've also double checked the paths of both files through inspection, which just downloaded both files with chromium.
My concluding question:
Is this reference (link element href) pointing to an internal intelligence or to a "physical" available file at runtime? And if secondly, which one (generated (html/dart) or source)?
To avoid misunderstandings, I've added a list of my repo:
foo
packages
examples
assets
dart.js
example.html
web
out
foo.html.dart
foo.html
build.dart
Component file (foo.html) is missing the <html><body>...</body></html> tags:
<!DOCTYPE html>
<html>
<body>
<element name="x-foo" constructor="FooComponent" extends="button">
...
</element>
</html>
</body>
Both files (examples.html and foo.html) must be in the same base directory:
web
examples.html
foo.html
...
Then, examples.html need be used as argument inside build.dart:
build(new Options().arguments, ['web/example.html']);
And, finally, foo.html (that is, web/foo.html) must be the one to be linked:
<link rel="components" href='foo.html'>
The way you have it in your main HTML file is correct. You reference foo.html because the referencing HTML document needs to be compiled with dwc. dwc will take the main HTML file and compile it and all the the components it includes. The component are completely compiled to Dart and they .html files won't be used anymore.
If you're trying to edit example.html to include your component, you'll need to compile example.html, and not foo.html. You'll still generate foo.html.dart, but also example.html.dart and a bootstrap script to load everything up.

Resources