I am using Adobe Flash CC to create EaselJS output manipulating the HTML5 canvas. However there seems to be a massive oversight in the ability to pass parameters to event listeners.
The issue is that I offer multiple animation outputs for compatibility, one using EaselJS and one using Raphael, however the interface that controls these remains the same, these are plain HTML elements with data stored in attributes that I wish to call functions written in the Flash IDE by triggering events and passing parameters.
I could easily find ways to avoid using EventDispatcher such as registering them with the root object and calling them directly with custom handlers. However I would rather keep my Flash IDE output as universally compatible as possible and not pollute object's namespaces I have little control over. I consider it a bad design pattern to write code in the Flash IDE that won't work without external aid.
Is there a way to pass parameters from an EaselJS event dispatcher to the listening events? I know on() provides a data parameter but that is useless as I need to pass different parameters to the same event depending upon user interaction.
You can put any properties on an Event object that you want. When you dispatch an event, you can use a string like "complete" (which is better if you don't need parameters, since it won't generate an object if there are no listeners). If you have parameters, create a new createjs.Event, and put whatever properties on it that you want:
var event = new createjs.Event("complete");
event.time = new Date();
this.dispatchEvent(event);
Then you can inspect the event object in your handler.
myObject.addEventListener("complete", handler); // add a listener
function handler(event) {
console.log(event.time);
}
Hope that helps!
Related
Is there a tool for Node.js or the browser whereby I can find out which objects hold a reference to object X?
Right now I am using Backbone for front-end development and even though I remove views there still seem to be references to them afterwards.
The reason I suspect this behavior in the first place is because I am using plugin/addons for Backbone debugging in Chrome and Mozilla.
This does make me wonder if perhaps these programs themselves are the ones holding references to the Backbone objects!
First of all,Sadly there is no way to do that.
You can check who calls a function and object which specific variable holds as reference though.
It's not because of Backbone/Node.js but Javascript itself.
When you substitute object/Array, javascript only passes target memory address to the variable.
But I assume it's highly possible that the reason why you are having memory leak problem is not because of references from another variables but event handlers which is often seen in Backbone uses(also knowns as "zombie view")
Once you set events handler in a View, You need to make sure all events are unset before you actually delete the view(.remove()) unless You are using only listenTo for Backbone events and this.$el for jQuery events.
Because events set via listenTo and this.$el are automatically removed by Backbone Core when you remove a View.
And events set by Model.on or global jQuery$ would not be so.
So Please check your whole code whether You are using .on or global jQuery Object to set events, in the case You have, replace them into listenTo or this.$el.on or manually unset them Before You remove them.
I have an object, which I need to control from another object.
What's a better practice and why?
Reference the object by window.object = this in it's constructor and then call window.object.method() from the other one
or
Start listening like $(window).on 'objectEvent' and triggering the event from the other object like $(window).trigger('objectEvent')?
I am currently using the second approach, but I'm wondering, whether it's the right one.
The second approach is the least bad. You want to avoid polluting the global namespace, ie: adding properties to window.
In the second case you are adding listeners to it, which isn't that bad if you namespace event names, but the best option would be to use an intermediary object and implement the Pub/Sub pattern, so both objects interact b/w themselves through it.
I've some reports where I use JavaScript variables between different event handlers.
Example:
//Data Set beforeOpen:
fooList = "";
//Data Set fetch:
fooList += row['foos'] + ", ";
//Dynamic Text expression, somewhere in the report:
fooList
This code works for me in 2.6.2. (There is an invisible table above this DynamicText which triggers Data Set use)
Documentation says, that I should use reportContext.setGlobalVariable("foo","bar");, but I haven't yet found, that using simple assignments is discouraged.
What are disadvantages of using simple assignments in BIRT Javascript event handlers, such as foo="bar"; and reading it later in another event handler?
By setting your variables this way you are in fact able to access them anywhere in the scripting layer. If you need to extend the reach of the variable into compiled code via a Java event handler, you would need to use the global variable to use the variable.
There is no added cost to this approach and making it a best practice ensures if you do cross any boundaries the variable's state is maintained and available for you anywhere you may need it.
Good Luck!
I recently upgraded our project's jQuery file from 1.4.2 to 1.4.4 and it appears that as of 1.4.3 the way we have been using jQuery.data has stopped working.
We have this code:
var events = $(window).data('events');
if (events.scroll)
if (!events.scroll.include(handler))
$(window).scroll(handler);
the purpose is to prevent this particular handler from being bound multiple times.
In 1.4.2, this works fine. In 1.4.4, events is undefined.
function handler() {
//do something
}
$(document).ready(function(){
$(window).scroll(handler);
$('div#test').scroll(handler);
$(window).data('events') -> undefined
$('div#test').data('events') -> Object
});
What changed with this API? How should I list events for window?
I have changed the first line to this:
var events = $(window).data('__events__').events;
a bit messy-looking, but the ability to wire events to plain objects is compelling.
There was a change in jQuery 1.4.3+ for event types, to avoid object name collisions, for window (or any other plain object) use the key "__events__" instead, like this:
var events = $(window).data('__events__');
The same __events__ key is used for any objects that don't have a .nodeType property (which window doesn't, so it's treated like a plain object here).
To be clear that this was a conscious, intentional change, it's included in the jQuery 1.4.3 release notes:
JavaScript Objects
A number of changes were made to when .data() is used on JavaScript objects (or, more accurately, anything that isn’t a DOM node). To start whenever you set data on a JavaScript object the data is set directly on the object – instead of going into the internal data object store. Additionally events that are attached to objects are put in a new __events__ property that is actually a function. This was done to allow events to be attached directly to an object, be garbage collected when the object is collected, and not be serialized by a JSON serializer. These changes should make jQuery’s data and event systems much more useful on JavaScript objects.
The basic API still seems to work.
However, it doesn't seem to work on the window.
So, the API for accessing jQuery-assigned events hasn't really changed; it just no longer applies to the window. That doesn't exactly sound like an intentional decision, and the 1.4.3 -> 1.4.4 changelog makes no mention of it.
Sounds like a bug, and it might have to do with the recent changes to data now being able to access HTML5 data- attributes. Consider filing a ticket for it :/
You know what I liked best about obtrusive javascript? You always knew what it was going to do when you triggered an event.
<a onclick="thisHappens()" />
Now that everybody's drinking the unobtrusive kool-aid it's not so obvious. Calls to bind events can happen on any line of any number of javascript file that get included on your page. This might not be a problem if you're the only developer, or if your team has some kind of convention for binding eventhandlers like always using a certain format of CSS class. In the real world though, it makes it hard to understand your code.
DOM browsers like Firebug seem like they could help, but it's still time consuming to browse all of an element's event handler properties just to find one that executes the code you're looking for. Even then it usually just tells you it's an anonymous function() with no line number.
The technique I've found for discovering what JS code gets executed when events are triggered is to use Safari's Profiling tool which can tell you what JS gets executed in a certain period of time, but that can sometimes be a lot of JS to hunt through.
There's got to be a faster way to find out what's happening when I click an element. Can someone please enlighten me?
Check out Visual Event... it's a bookmarklet you can use to expose events on a page.
If you're using jQuery you can take advantage of its advanced event system and inspect the function bodies of event handlers attached:
$('body').click(function(){ alert('test' )})
var foo = $('body').data('events');
// you can query $.data( object, 'events' ) and get an object back, then see what events are attached to it.
$.each( foo.click, function(i,o) {
alert(i) // guid of the event
alert(o) // the function definition of the event handler
});
Or you could implement your own event system.
To answer your question, try using the Firebug command line. This will let you use JavaScript to quickly grab an element by an ID, and then iterate through its listeners. Often, if used with console.log, you'll even be able to get the function definitions.
Now, to defend the unobtrusive:
The benefit I find in unobtrusive JavaScript is that it is a lot easier for me to see the DOM for what it is. That said, I feel that it is generally bad practice to create anonymous functions (with only few exceptions). (The biggest fault I find with JQuery is actually in their documentation. Anonymous functions can exist in a nether-world where failure does not lead to useful output, yet JQuery has made them standard.) I generally have the policy of only using anonymous functions if I need to use something like bindAsListener from Prototype.
Further, if the JS files are properly divided, they will only be addressing one sub-set of the DOM at a time. I have an "ordered checkbox" library, it is in only one JS file which then gets re-used in other projects. I'll also generally have all of the methods of a given sub-library as member methods of either a JSON object or a class and I have one object/class per js file (just as if I were doing everything in a more formalized language). If I have a question about my "form validation code", I will look at the formValidation object in formvalidation.js.
At the same time, I'll agree that sometimes things can become obtuse this way, especially when dealing with others. But disorganized code is disorganized code, and it is impossible to avoid unless you are working by yourself and are a good programmer.
In the end, though, I would rather deal with using /* */ to comment out most of two or three js files to find misbehaving code, then go through the HTML and remove the onclick attributes.
Calling it "kool-aid" seems unfair. DOM Level 2 events solve specific problems with inline event handling, like the conflicts that always result. I don't look back to writing code to use window.onload that has to check whether someone else has assigned it before, and sometimes having it overriden by accident or out of sloppiness. It also ensures a better separation of the structure (HTML) and behaviour (JS) layers. All in all, it's a good thing.
Regarding debugging, I don't think there's any way to solve the event handlers being anonymous functions, other than nagging the authors to use named functions where possible. If you can, tell them that it produces more meaningful call stacks and makes the code more maintainable.
One thing: you shouldn't be able to see what will happen in JavaScript by looking at the HTML code. What nuisance is that? HTML is for structure.
If you want to check what events are bound to certain elements, there's a bookmarklet called visual event for now, and firebug 1.6 (IIRC) will have some sort of event inspector.