Recently i've bumped into a problem that an external javascript, declared in the html, which is then @Templated by a Java class using Errai UI, doesn't work. The issue might be easy for experienced ones, however, i'm going to describe the solution here as i've spent really a lot time on this.
Errai is a great GWT-based framework. Its module Errai UI allows to work with "pure HTML" comfortably. For example, you may have a look at the errai-tutorial example, where bootstrap is actually used for styling the page.
I wanted to use a bootstrap-slider, that "paints" beautiful sliders. So I put
The reason: when the js gets executed, the html isn't loaded yet.
Solution:
So we use onLoad() which is is called immediately after a widget becomes attached to the browser's document.
Important: Obligatorily call .setWindow(ScriptInjector.TOP_WINDOW). It puts the scripts declaration into the head of the host page. Otherwise, the scripts don't work.
Moreover: The solution above actually causes error, which you can observe in the console of the browser dev tools. It's message says that bootstrap js can't work without jquery. The reason is that ScriptInjector injects scripts asynchronously. It doesn't wait for jquery library to be loaded and starts loading boostrap. The solution is load libraries in a strict order. Method setCallback allows to achieve it:
Great thanks for openness and help to Max Barkley.
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/6.1.7/bootstrap-slider.js" type="text/javascript"></script>into the gwt host page head. However, it didn't work. Also putting this line into the html template didn't help.
The reason: when the js gets executed, the html isn't loaded yet.
Solution:
@Templated("MyTemplate.html#mytag")
public class MyTemplate extends Composite {
@Override
protected void onLoad() {
ScriptInjector.fromUrl("https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js").setWindow(ScriptInjector.TOP_WINDOW).inject();
ScriptInjector.fromUrl("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js").setWindow(ScriptInjector.TOP_WINDOW).inject();
ScriptInjector.fromUrl("https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/6.1.7/bootstrap-slider.js").setWindow(ScriptInjector.TOP_WINDOW).inject();
}
So we use onLoad() which is is called immediately after a widget becomes attached to the browser's document.
Important: Obligatorily call .setWindow(ScriptInjector.TOP_WINDOW). It puts the scripts declaration into the head of the host page. Otherwise, the scripts don't work.
Moreover: The solution above actually causes error, which you can observe in the console of the browser dev tools. It's message says that bootstrap js can't work without jquery. The reason is that ScriptInjector injects scripts asynchronously. It doesn't wait for jquery library to be loaded and starts loading boostrap. The solution is load libraries in a strict order. Method setCallback allows to achieve it:
@Override
protected void onLoad() {
ScriptInjector.fromUrl("https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js").setCallback(new Callback() {
@Override
public void onSuccess(Void result) {
ScriptInjector.fromUrl("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js").setCallback(new Callback() {
@Override
public void onFailure(Exception reason) {
// TODO Auto-generated method stub
}
@Override
public void onSuccess(Void result) {
ScriptInjector.fromUrl("https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/6.1.7/bootstrap-slider.js").setWindow(ScriptInjector.TOP_WINDOW).inject();
}
}).setWindow(ScriptInjector.TOP_WINDOW).inject();
}
@Override
public void onFailure(Exception reason) {
// TODO Auto-generated method stub
}
}).setWindow(ScriptInjector.TOP_WINDOW).inject();
}
It looks awful and needs to be refactored, but illustrates the idea,Great thanks for openness and help to Max Barkley.
0 коммент.:
Отправить комментарий