I have an application that is half GWT and half Backbone.js. We're transitioning the app from GWT to Backbone so as we add new components, they're in Backbone. We're also replacing some existing components with Backbone as well.
There's a component that I'm attempting to replace that still needs to be able to let its GWT container know when certain events occur so that the container can impact other GWT components. I have a native function in GWT that references a Global namespace on which a function is defined in Javascript. That function renders the Backbone component, so GWT doesn't have a reference to the component itself.
I tried defining a custom DOM Event in GWT and then triggering that event from the Backbone code, but either I did it wrong, or that's not the way to do it.
I referenced these questions in creating my custom event: How to add CSS AnimationEnd event handler to GWT widget? & GWT Custom Events
I made two attempts at triggering the custom event from Backbone and having GWT listen for it, neither worked.
I need help triggering an event (or calling a callback, or something equivalent) from Javascript (Backbone.js) that will be "heard" (or called or whatever) in GWT.
CODE
Code common between two attempts is how the Backbone component is rendered and how the event is triggered:
From class BackboneController.java
:
public static void loadMessageEntry(final String selector, final String type, final QuipuId conversationID, final QuipuId messageID, final boolean enterIsSubmit) {
String messageIDString = messageID.getId();
String enterRole = enterIsSubmit ? "submit" : "newline";
if(messageID.equals(QuipuId.NULL)) {
messageIDString = "";
}
showMessageEntry(selector, type, conversationID.getId(), messageIDString, enterRole);
}
private static native void showMessageEntry(String selector, String type, String messageId, String conversationId, String enterRole) /*-{
var intervalTimer = $wnd.setInterval(function() {
if($wnd.Namespace.MessageEntry) {
$wnd.Namespace.MessageEntry.displayMessageEntry(selector, type, messageId, conversationId, enterRole);
$wnd.clearInterval(intervalTimer);
}
}, 500);
}-*/;
From class myClientBootstrap.js
:
Namespace.MessageEntry = Namespace.MessageEntry || {};
Namespace.MessageEntry.displayMessageEntry = function(selector, type, conversationID, messageID, enterRole) {
var messageEntry,
instanceName = selector.slice(1);
if(CKEDITOR.instances[instanceName]) {
CKEDITOR.instances[instanceName].trigger("show");
} else {
messageEntry = new MessageEntry( {
model: new RTEModel({mode: 'inline', type: type, conversationID: conversationID, messageID: messageID}),
enterRole: enterRole
});
$(selector).append(messageEntry.$el);
}
};
From class MessageEntryView.js
:
// called when the upload button is clicked
openDocumentUploader: function() {
$("." + this.model.get("id")).trigger('messageEntry',["documentUpload"]);
}
From class MessageEntry.java
:
Attempt 1
private native void registerMessageEntryEventHandler(final Element messageEntry, final MessageEntryHandler handler) /*-{
var callback = function() {
[email protected]::onMessageEntryEvent(Lmypath/client/MessageEntryEvent;)();
}
messageEntry.addEventListener("messageEntry", callback, false);
}-*/;
private void initLayout() {
initWidget(mainDockLayoutPanel);
Conversation model = conversationController.getModel();
messageEntryPanel.getElement().addClassName("richTextAreaId" + model.getId());
BackboneController.loadMessageEntry(".richTextAreaId" + model.getId(), "message", model.getId(), QuipuId.NULL, (Boolean)PreferencesModel.getInstance().isAutoSubmit());
registerMessageEntryEventHandler(messageEntryPanel.getElement(), new MessageEntryHandler() {
@Override
public void onMessageEntryEvent(MessageEntryEvent event) {
if(event.getEventType() == "documentUpload") {
MessageEntry.this.switchToDocumentUpload();
}
}
});
mainDockLayoutPanel.addStyleName(MessageEntryBundle.instance.css().container());
modeSimplePanel.add(messageEntryPanel);
mainDockLayoutPanel.add(modeSimplePanel);
}
Attempt 2
private void initLayout() {
initWidget(mainDockLayoutPanel);
Conversation model = conversationController.getModel();
messageEntryPanel.getElement().addClassName("richTextAreaId" + model.getId());
BackboneController.loadMessageEntry(".richTextAreaId" + model.getId(), "message", model.getId(), QuipuId.NULL, (Boolean)PreferencesModel.getInstance().isAutoSubmit());
addDomHandler(new MessageEntryHandler() {
@Override
public void onMessageEntryEvent(MessageEntryEvent event) {
if(event.getEventType() == "documentUpload") {
MessageEntry.this.switchToDocumentUpload();
}
}
}, MessageEntryEvent.getType());
mainDockLayoutPanel.addStyleName(MessageEntryBundle.instance.css().container());
modeSimplePanel.add(messageEntryPanel);
mainDockLayoutPanel.add(modeSimplePanel);
}
Made another attempt, this has a few more differences than between the first two. When we create our namespace, we do _.extend(Namespace, Backbone.Events)
so that we can trigger events from GWT that the Backbone code will listen for. I decided to try getting it to work in the other direction. It didn't.
Attempt 3
From MessageEntryView.js
:
openDocumentUploader: function() {
Namespace.trigger(Namespace.Events.UPLOAD);
}
From MessageEntry.java
:
private native void registerUploadListener(MessageEntry msgEntry) /*-{
$wnd.Namespace.on($wnd.Namespace.Events.UPLOAD, function() {
[email protected]::switchToDocumentUpload();
});
}-*/;
private void initLayout() {
initWidget(mainDockLayoutPanel);
Conversation model = conversationController.getModel();
messageEntryPanel.getElement().addClassName("richTextAreaId" + model.getId());
BackboneController.loadMessageEntry(".richTextAreaId" + model.getId(), "message", model.getId(), QuipuId.NULL, (Boolean)PreferencesModel.getInstance().isAutoSubmit());
registerUploadListener(this);
mainDockLayoutPanel.addStyleName(MessageEntryBundle.instance.css().container());
modeSimplePanel.add(messageEntryPanel);
mainDockLayoutPanel.add(modeSimplePanel);
}
Attempt 3 is what did it. I just called the GWT method incorrectly from the native method.
Using the Global namespace and extending it to use Backbone events, I just have the Backbone view trigger the Global event and the GWT view listen for the event.
Attempt 3
From MessageEntryView.js
:
openDocumentUploader: function() {
Namespace.trigger(Namespace.Events.UPLOAD);
}
From MessageEntry.java
:
private native void registerUploadListener(MessageEntry instance) /*-{
$wnd.Namespace.on($wnd.Namespace.Events.UPLOAD, function() {
[email protected]::switchToDocumentUpload()();
});
}-*/;
private void initLayout() {
initWidget(mainDockLayoutPanel);
Conversation model = conversationController.getModel();
messageEntryPanel.getElement().addClassName("richTextAreaId" + model.getId());
BackboneController.loadMessageEntry(".richTextAreaId" + model.getId(), "message", model.getId(), QuipuId.NULL, (Boolean)PreferencesModel.getInstance().isAutoSubmit());
registerUploadListener(this);
mainDockLayoutPanel.addStyleName(MessageEntryBundle.instance.css().container());
modeSimplePanel.add(messageEntryPanel);
mainDockLayoutPanel.add(modeSimplePanel);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With