How can I dynamically modify the body onload tag of a Wicket 1.6 page in Wicket?
I want to add a JavaScript function to the "onload" attribute that requires dynamic parameters that I generate in Java.
Thanks in advance
It's better to use following approach.
In any component that require some onLoad action to be performed add following method:
#Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
response.render(
OnDomReadyHeaderItem.forScript("alert('REPLACE ALERT BY YOUR SCRIPT')"));
}
If you need to prepare script dynamically with extra params and etc. I recommend following:
private final static TextTemplate template
= new PackageTextTemplate(YourComponentOrPage.class, "your-js-template.js");
#Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
Map<String, Object> params =new HashMap<String, Object>();
params.put("parameter1", parameter1Value);
params.put("parameter2", parameter2Value);
response.render(OnDomReadyHeaderItem.forScript(template.asString(params)));
}
And "your-js-template.js" may look like:
alert('Hi!, ${parameter1}. My name is ${parameter2}');
Currently Wicket 6.x has a specific class for onLoad events. No more need for any hackish solutions:
#Override
public void renderHead(IHeaderResponse response)
{
super.renderHead(response);
response.render(OnLoadHeaderItem.forScript(yourDynamicScript));
}
Related
I'm trying to add a custom HeaderResponseContainer in my wicket application. The tutorial looks quite simple (see Positioning of contributions), but when I add these lines and run the application I alwas get an IllegalStateException:
java.lang.IllegalStateException: No FilteringHeaderResponse is present in the request cycle. This may mean that you have not decorated the header response with a FilteringHeaderResponse. Simply calling the FilteringHeaderResponse constructor sets itself on the request cycle
at org.apache.wicket.markup.head.filter.FilteringHeaderResponse.get(FilteringHeaderResponse.java:165)
at org.apache.wicket.markup.head.filter.HeaderResponseContainer.onComponentTagBody(HeaderResponseContainer.java:64)
at org.apache.wicket.markup.html.panel.DefaultMarkupSourcingStrategy.onComponentTagBody(DefaultMarkupSourcingStrategy.java:71)
...
Yes, I already saw the note about FilteringHeaderResponse. But I am not sure where I should call the constructor. I already tried to add it in renderHead before calling response.render but I still get the same exception:
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
FilteringHeaderResponse resp = new FilteringHeaderResponse(response);
resp.render(new FilteredHeaderItem(..., "myKey"));
}
You can create a decorator that wraps responses in a FilteringHeaderResponse:
public final class FilteringHeaderResponseDecorator implements IHeaderResponseDecorator {
#Override
public IHeaderResponse decorate(IHeaderResponse response) {
return new FilteringHeaderResponse(response);
}
}
And that set it during application initialization:
Override
public void init() {
super.init();
setHeaderResponseDecorator(new FilteringHeaderResponseDecorator());
}
I just ran into this same problem and found that the Wicket In Action tutorial leaves out the part about setting up a custom IHeaderResponseDecorator in your main Wicket Application init. The Wicket guide has a more thorough example:
Apache Wicket User Guide - Put JavaScript inside page body
You need something like this in your wicket Application:
#Override
public void init()
{
setHeaderResponseDecorator(new JavaScriptToBucketResponseDecorator("myKey"));
}
/**
* Decorates an original IHeaderResponse and renders all javascript items
* (JavaScriptHeaderItem), to a specific container in the page.
*/
static class JavaScriptToBucketResponseDecorator implements IHeaderResponseDecorator
{
private String bucketName;
public JavaScriptToBucketResponseDecorator(String bucketName) {
this.bucketName = bucketName;
}
#Override
public IHeaderResponse decorate(IHeaderResponse response) {
return new JavaScriptFilteredIntoFooterHeaderResponse(response, bucketName);
}
}
I was trying to wrap some jquery function to GWT, run below js code, the size is 2.
var html="<div><p>paragraph</p><div>second</div></div>";
var size=$(html).get(0).children.length;
alert(size);
but run below GWT code
select(html).get(0).getChildCount();
just return 0, the select function is like below:
public class JQuery extends JavaScriptObject {
protected JQuery() {
}
public static final native JQuery select(String selector) /*-{
return $wnd.jQuery(selector);
}-*/;
public final native Element get(int index) /*-{
return this.get(index) || null;
}-*/;
}
I'd like to know why it just loses the children elements from JSNI method, and what's the right way to this wrapping to let it behave exactly same to native jquery?
Thanks.
-------------EDIT------------------------------------------------------------
I test above JSNI code in a real gwt project and it works fine, the children elements are returned from js to java. But in GwtTestCase problem exists.
public class JQueryTest extends GWTTestCase {
#Override
public String getModuleName() {
return "com.jsnitest.JsniTest";
}
public void testSelectHtml() {
ScriptInjector.fromUrl("http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js").setWindow(
ScriptInjector.TOP_WINDOW).setCallback(new Callback<Void, Exception>() {
#Override
public void onFailure(Exception reason) {
}
#Override
public void onSuccess(Void result) {
int childCount = select("<div><p>paragraph</p><div>second</div><ul></ul></div>").get(0).getChildCount();
//Fail! childCount=0
assertEquals(3, childCount);
}
}).inject();
}
}
gwtquery a.k.a. gQuery is a jQuery-like API written in GWT.
Following the principle of DRY, I would use this library instead of wrapping jQuery.
The only reason I see to wrap jQuery in GWT is that you needed very specific features in jQuery not present in gQuery, although gQuery has almost completed the jQuery API.
I have a simple wrapper around a WYSIWYG editor (TinyMCE). I'm using JSNI to call a Java instance method (onClick) from Javascript. However the Java onClick method always gets called on the same Java instance (the last one created), no matter the editor that originated it.
private SimplePanel panel;
private TextArea ta;
private String id;
public TinyMCE(AbstractTinyMCEConfiguration config) {
id = HTMLPanel.createUniqueId();
ta = new TextArea();
ta.getElement().setId(id);
panel = new SimplePanel();
panel.add(ta);
initWidget(panel);
init(config);
}
protected native void init(AbstractTinyMCEConfiguration conf) /*-{
var ins = this;
$wnd.tinyMCE.init({
// General options
mode : conf.#com.chip.tinymce.client.AbstractTinyMCEConfiguration::getMode()(),
setup : function(ed) {
ed.onClick.add(function(ed,e) {
alert(ed.id);
ins.#com.chip.tinymce.client.TinyMCE::onClick(Lcom/google/gwt/dom/client/NativeEvent;)(e);
});
}
});
}-*/;
private void onClick(NativeEvent e) {
GWT.log("onClick " + id);
ClickEvent.fireNativeEvent(e, this);
}
I'm not sure if I can call a Java method from a Javascript funcion that is inside another funcion. Maybe that explains my problem... or maybe I'm missing something. Thanks for your help.
I think TinyMCE has one shared configuration for all editors, and that is the problem here.
It probably does not make much sense to hand the configuration to the constructor if it is shared...
Why not add a static map that maps the id back to the Java instance, something like
// ....
private static Map<String, TinyMCE> idMap = new HashMap<String, TinyMCE>();
public TinyMCE() {
// ...
idMap.put(id, this);
}
// call this from Javascript with (ed.id, e)
private static void onClick(String id, NativeEvent e) {
idMap.get(id).onClick(e);
}
I am wanting to use the phonegap audio api in GWT using JSNI.I cannot figure out how to code the methods in JSNI.
Wondering if anyone know of any tutorials.They javascript methods are really pretty simple.
http://docs.phonegap.com/phonegap_media_media.md.html
Basically it sounds like it would be something like this:
public final class Media extends JavaScriptObject {
protected Media() {}
public static native final Media newInstance(String src, Command command) /*-{
var callback = function() { command.execute(); };
return new Media(src, callback);
}-*/;
public native final void getCurrentPosition(AsyncCallback<String> command) /*-{
var callback = function(position) { command.onSuccess('' + position); };
this.getCurrentPosition(callback);
}-*/;
public native final void play() /*-{
this.play();
}-*/;
//... more methods here
}
Usage:
Media m = Media.newInstance("http://www.example.com/src.mp3", new Command() {
#Override
public void execute() {
// Code executed after Media is created.
}
});
m.getCurrentPosition(new AsyncCallback<String>() {
#Override
public void onSuccess(String position) {
Window.alert(position);
}
});
m.play();
That's a rough sketch, if you know more about what the type being passed to the callback is you can do nicer things like have it be an int or another JS Overlay Type.
The API is kind of weird because everything is apparently asynchronous, but that's life.
Once you've gotten the hang of writing GWT JSNI bindings it's pretty straightforward.
If you end up getting further down this road, it would be awesome if you open-sourced your GWT wrapper library so other GWT developers could write some iPhone/Android apps.
I just need the play method really.I am not quite as knowledgeable to do this correctly I guess.That code looks really foreign to me :-)
Still cannot accept your answer.The site does not recognize me it is strange.
I get the following error when trying to use the media in my onModuleLoad
The constructor TESTPHONEGAP.Media(String, new Command(){}) is undefined
Media m = new Media("test.mp3", new Command() {
#Override
public void execute() {
}
});
m.play()
Using your class as an "inner class" in same file as my main onModuleLoad
I am developing a GWT application with presenter, dispatcher and Gin.
I have a presenter which is retrieving an ArrayList<JobPosting> from
server and firing a ManageJobsEvent.
dispatcher.execute(new GetJobPostings(userId), new
DisplayCallback<GetJobPostingsResult>(display) {
#Override
protected void handleFailure(Throwable e) {
e.printStackTrace();
Window.alert(SERVER_ERROR);
}
#Override
protected void handleSuccess(GetJobPostingsResult value) {
eventBus.fireEvent(new ManageJobsEvent(value.getUserId(),
value.getJobPostings()));
}
});
I get the callback to onPlaceRequest(PlaceRequest request) of my
another presenter
but how do i get the ArrayList<JobPostings> set in the event.
I'm not sure I understand your problem correctly, but since you are passing the ArrayList<JobPostings> to the constructor of the ManageJobsEvent, why not just add a getter to retrieve it?