observe.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /**
  2. * AOP style event handling, for listening for method calls. Very similar to dojo.connect
  3. /* Add a listener for the execution of the given function slot on the given object.
  4. *
  5. * When object[eventName]() is executed the handler is called.
  6. * The optional before parameter can be used to indicate if the listener
  7. * should be fired before or after the default action (default is after)
  8. */
  9. exports.observe = function(object, eventName, listener, before) {
  10. if(!listener){
  11. throw new Error("No listener provided");
  12. }
  13. if(typeof object.observe === "function"){
  14. // CommonJS observable object
  15. return object.observe(eventName, listener);
  16. }
  17. var listenerProxy = function(that, args){//make sure we have unique function so we can remove it
  18. try{
  19. listener.apply(that, args);
  20. }catch(e){
  21. require("./process").print(e);
  22. }
  23. };
  24. if(typeof object.addListener === "function"){
  25. // NodeJS EventEmitter
  26. object.addListener(eventName, listener);
  27. return {
  28. observe: function(listener){
  29. return exports.observe(object, eventName, listener);
  30. },
  31. emit: function(event){
  32. object.emit(eventName, event);
  33. },
  34. dismiss: function(){
  35. object.removeListener(eventName, listener);
  36. }
  37. };
  38. }
  39. var afters, befores,
  40. main = object[eventName];
  41. if(typeof main != "function"){
  42. main = function(){};
  43. }
  44. if(main._afters){
  45. afters = main._afters;
  46. befores = main._befores;
  47. }
  48. else{
  49. befores = [];
  50. afters = [];
  51. var newFunc = object[eventName] = function(){
  52. for(var i = 0; i < befores.length; i++){
  53. befores[i](this, arguments);
  54. }
  55. try{
  56. return main.apply(this, arguments);
  57. }
  58. finally{
  59. for(var i = 0; i < afters.length; i++){
  60. afters[i](this, arguments);
  61. }
  62. }
  63. };
  64. newFunc._befores = befores;
  65. newFunc._afters = afters;
  66. }
  67. if(before){
  68. befores.push(listenerProxy);
  69. }
  70. else{
  71. afters.push(listenerProxy);
  72. }
  73. return createSignal();
  74. function createSignal(){
  75. var observers;
  76. return {
  77. observe: function(listener){
  78. afters.push(listener);
  79. },
  80. emit: function(){
  81. main.apply(object, arguments);
  82. },
  83. dismiss: function(){
  84. if(before){
  85. befores.splice(befores.indexOf(listenerProxy), 1);
  86. }
  87. else{
  88. afters.splice(afters.indexOf(listenerProxy), 1);
  89. }
  90. }
  91. };
  92. };
  93. };