How to fire events when plugin is loaded - javascript

In my plugin I need to be able to fire event(s) once the plugin was loaded.
I don't want to use the built in mechanism (adding it in the object params) since I need to be able to control the parameters which are sent along with the event firing.
The problem is that when I try to fire the event in onPluginReady it just doesn't fire.. While debugging I noticed that the m_proxies is empty (in JSAPIImpl::FireEvent), but if I try the same code for firing the event in the onMouseDown method then it works well.
This is my createJSAPI code:
FB::JSAPIPtr plugin::createJSAPI()
{
this->jsApi = JSApiPtr(new pluginAPI(FB::ptr_cast<plugin>(shared_from_this()), m_host));
return this->jsApi;
}
And this is the onPluginReady code:
void plugin::onPluginReady()
{
this->getRootJSAPI();
this->jsApi->fireMyEvent(this->myId);
}
and the event isn't fired, though this does:
bool plugin::onMouseDown(FB::MouseDownEvent *evt, FB::PluginWindow *)
{
this->jsApi->fireMyEvent(this->myId);
return false;
}
Why is that?
Thanks.

onPluginReady is likely to be called before your onLoad callback from the param tag gets called; that means your event handlers aren't attached yet. That's the reason that FireBreath provides the onload param callback -- it gives you a place to attach event handlers and find out that things are loaded.
Edit to clarify from comments:
The callback will be provided with a single parameter which contains a reference to your root JSAPI object. Note that in this case it is not the object or embed tag, just the JSAPI object, so you can use any methods or properties from there.

Related

Do Javascript Event listeners get destroyed after firing (by default)?

I have an event listener on an object which fires a function when the object changes.
This is the code:
window.parent.document.getElementById('campval').addEventListener("change", getscriptbuttons1());
This works perfectly the first time that the object changes however, all consecutive changes do not trigger the event listener.
Is this the normal behaviour of Javascript? What can I do to rectify this issue?
No, the event listener should get fired every time.
I think this error is due because you are calling the function instead of passing it as a parameter:
getscriptbuttons1 // passes the function
getscriptbuttons1() // calls the function and passes whatever it returns
Did you mean? :
window.parent.document.getElementById('campval').addEventListener("change", getscriptbuttons1);
No, they do not get destroyed. You have to remove them manually. The issue is that you are actually calling the function in the event listener. You need to change it to this: (no parens, don't call it)
window.parent.document.getElementById('campval').addEventListener("change", getscriptbuttons1);

Prototype fire on change event issue

This is my js file content:
window.onload = function() {
obj = document.getElementById("_accountwebsite_id");
Event.observe(obj, 'change', function () {
alert('hi');
});
}
I want to fire the on change event for my dropdown: _accountwebsite_id . The prototype library it is loaded before this file. I got no errors in the console. Where am i wrong ? thx
You're doing a lot of extra work here that Prototype does for you. First off, setting the document's onload method not only is really old-school, it also will clobber any previously set observer on that event.
$(document).observe('dom:loaded', function( ... ){...});
...is the modern way to register one (or more) event listeners to the document load event.
Next, you're using getElementById here, which will work, but does not return a Prototype-extended object in some browsers.
$('element-id');
...will both get the element reference and extend it if your browser failed to respect every aspect of prototypal inheritance.
Finally, this whole thing can be made both simpler and more bulletproof by using a deferred observer. Imagine if your interface DOM was updated by Ajax -- that would make your observer miss the events fired by this select element, because it was not referring to the same (===) element, even if the ID matched.
$(document).on('change', '#_accountwebsite_id', function(evt, elm){
alert(elm.inspect());
});
This observer will respond to any change event on an element with the correct ID, even if it was added after the observer was registered with the document.

Trigger event in Backbone.js and Saiku

I'm new to backbone. I have been looking it has been used in Saiku. I came across the below line.
Saiku.session.trigger('workspace:new', { workspace: this });
Is 'workspace:new' an event? How does backbone trigger recognize it as an event?
Short answer: yes, workspace:new is an event.
Backbone has several built-in events that you can listen for. But you can also trigger custom events, as this code does. The event is identified by only a string (in this case, "workspace:new"). When you call trigger on an object that inherits from Backbone's Event Module, that event "happens." As a second parameter to trigger, you can pass some data about the event, anything you want accessible from the event handler function.
Then, usually somewhere else, there will be code waiting for that event to happen. That is set up by calling the .on or .listenTo methods.
Here's a basic example: (See it in action on JSBin)
var model = new Backbone.Model();
model.on('my-event', function (data) {
console.log("my-event happened!");
console.log(data);
});
model.trigger('my-event');
model.trigger('my-event', 'some-data');
model.trigger('my-event', { anything: 'works' });

MyPlugin::createJSAPI only being called after a js interaction

I've noticed that the call to the createJSAPI method in my plugin is only called after I somehow try to interact with the actual DOM element.
Is there a way to make it happen before any javascript interaction is happening?
In the documentation for getRootJSAPI it states:
It is not recommended to call this from the constructor or before
setHost is called, as many JSAPI objects need the BrowserHost and a
weak_ptr to the Plugin class to function correctly
So when is it appropriate to call this method? in onPluginReady or onWindowAttached?
Thanks.
Edit
This is my createJSAPI code:
FB::JSAPIPtr plugin::createJSAPI()
{
this->jsApi = JSApiPtr(new pluginAPI(FB::ptr_cast<plugin>(shared_from_this()), m_host));
return this->jsApi;
}
And this is the onPluginReady code:
void plugin::onPluginReady()
{
this->getRootJSAPI();
this->jsApi->fireMyEvent(this->myId);
}
and the event isn't fired, though this does:
bool plugin::onMouseDown(FB::MouseDownEvent *evt, FB::PluginWindow *)
{
this->jsApi->fireMyEvent(this->myId);
return false;
}
Why is that?
As for the build in onload mechanism, I need my own, since I need to pass some parameters to that fired event.
Thanks.
You can call this method during or after onPluginReady -- that's one of the main purposes of the function.
EDIT:
To answer your further question, onPluginReady is likely to be called before your onLoad callback from the param tag gets called; that means your event handlers aren't attached yet. That's the reason that FireBreath provides the onload param callback -- it gives you a place to attach event handlers and find out that things are loaded.

Calling V8 function causes access violation

I have a global event manager, allowing you to listen with lambdas to string event names.
// somewhere in the ModuleScript class
Event->Listen("WindowResize", [=]{
// ...
});
Now, I want to register to events from JavaScript, too. Therefore, I wrote this callback.
v8::Handle<v8::Value> ModuleScript::jsOn(const v8::Arguments& args)
{
// get pointer to class since we're in a static method
ModuleScript *module = (ModuleScript*)HelperScript::Unwrap(args.Data());
// get event name we want to register to from arguments
if(args.Length() < 1 || !args[0]->IsString())
return v8::Undefined();
string name = *v8::String::Utf8Value(args[0]);
// get callback function from arguments
if(args.Length() < 2 || !args[1]->IsFunction())
return v8::Undefined();
v8::Handle<v8::Function> callback =
v8::Local<v8::Function>::Cast(args[1]->ToObject());
// register event on global event manager
module->Event->Listen(name, [=]{
// create persistent handle so that function stays valid
// maybe this doesn't work, I don't know
v8::Persistent<v8::Function> function =
v8::Persistent<v8::Function>::New(args.GetIsolate(), callback);
// execute callback function
// causes the access violation
function->Call(function, 0, NULL);
});
return v8::Undefined();
}
When the event is triggered, the application crashes with a access violation. My thoughts are that either the function object isn't valid at this time anymore, or it is a JavaScript scope issue. But I couldn't figure it out.
What causes the access violation and how to overcome it?
I believe there are several potential issues here.
First, you're not using a persistent handle to hold the JavaScript function after ModuleScript::jsOn() terminates. By the time your event handler is invoked, the function might be gone. Consider making callback a persistent handle.
Second, your event handler needs to enter an appropriate V8 context before calling the JavaScript function. Depending on your architecture, explicitly locking and entering the V8 isolate may be required as well.
Third (and this may not be an issue in your specific scenario), you need to manage the lifetime of the V8 isolate. If your event manager fires events on background threads, you have to make sure your event handler somehow prevents the isolate from being disposed from another thread. Unfortunately this is one area where the V8 API doesn't provide much help.
Fourth, to prevent a leak, your event handler should dispose the persistent function handle after invoking the function.
Good luck!

Categories

Resources