[ALOY-438] Proxy off() function from Backbone is not working
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | High |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2014-08-06T20:41:27.000+0000 |
Affected Version/s | n/a |
Fix Version/s | Alloy 0.3.4, 2012 Sprint 26 |
Components | Runtime |
Labels | qe-automatedtest, qe-manualtest |
Reporter | Tony Lukasavage |
Assignee | Tony Lukasavage |
Created | 2012-12-19T23:54:10.000+0000 |
Updated | 2014-08-06T20:41:27.000+0000 |
Description
In ALOY-370, a fix was put in place so that developers would be able to define functions for markup event handlers with either function declarations or expressions.
and elements, which use the same method for tying markup eventing to code. For example, devs often call model.fetch() in their controllers, which wouldn't fire any event handlers if we push the event handler code to the end.
// function declaration
function doClick() {}
// function expression
var doClick = function() {}
Expressions did not work before ALOY-370 as the event handlers were created before the function assignment, causing the event handler callback function to be undefined. To get around this, the reference to the event handler function was deferred inside of an anonymous caller. So:
$.someProxy.on('click', myFunction);
// became
$.someProxy.on('click', function() {
myFunction.apply(this, Array.prototype.slice.apply(arguments));
});
In this way, it didn't matter how the event handler function was defined or where, it would be in scope and defined by the time the event handler was actually fired. The problem is that now when you attempt to remove the event handler from the above code, it doesn't work because the functions won't match. The developer will be passing 'myFunction', but the eventing system has the anonymous function as its callback.
// won't work since we wrapped myFunction in an anonymous function
$.someProxy.off('click', myFunction);
So the problem is how do we maintain the ability to reference both function declarations and expressions, but still be able to have developers simply remove these functions without having to worry about an anonymous wrapper?
possible options
We go back to not supporting function expressions. This might not be so bad as all alloy examples use function declarations, and it remained like that up til version 0.3.2 before 1 person mentioned it. A small bit of documentation in the guides would make this easy to convey.
We move the event handler declaration code after the controller code. This seems like a logical, simple solution, but there is a distinct drawback. A developer will not be able to manually trigger these events if they want from the controller during its initial execution. For example:
// this would still work
$.win.on('open', function() {
$.someProxy.trigger('click');
});
// but this would not, but it also wouldn't throw an exception. It just wouldn't fire
// any event since the event handler would not have been defined yet.
$.someProxy.trigger('click');
This may not be a very common use case with UI components, but it is with
Brain dump before I go to bed. A possible solution to cover all bases would be using minimal runtime logic to determine whether or not the setting of an event handler should be done before the controller code, or deferred until after the controller code (if function expressions are used). Here's a rough idea of how it would go:
I tested this with plain old titanium development, hence the use of addEventListener for testing, rather than the Backbone on() and off().
Additional revision for final implementation, showing how this will be handled for an arbitrary number of handlers:
The bulk of this issue has been resolved and off() now works again. There is a specific scenario in which a small bit of functionality might not work, and this is covered in ALOY-441.
Proxy off() function sample is present in test/apps/basics/controller_events Verified fixed on 1_0_X master branch android device: 4.2 iPhone devices: iPhone 6 and iPad 4.3.5 TiSDK: 3.0.2.v20130128161704 CLI: 3.0.23 Closing.