53

Responder

Objective
  • Responder

An instance of Responder automatically sends notification messages to one or several instances. Responder instances can be linked so notifications are automatically transmitted from one responder to another.

  1. function Responder() {
  2. }
  3.  
  4. Responder.prototype = Object.create(Objective.prototype);
  5.  
  6. Object.defineProperty(Responder.prototype, 'constructor', { value: Responder, enumerable: false, writable: true });

An instance of Responder inherits from the class Objective.

  1. Object.defineProperty(Responder.prototype, 'nextResponders', {
  2.     get:    function() {
  3.         return this._nextResponders || null;
  4.     },
  5.     set:    function(responders) {
  6.         if (! (responders === null || (Array.isArray(responders) && responders.every((r) => r instanceof Responder))))
  7.             throw new TypeError();
  8.  
  9.         this._nextResponders = responders;
  10.     }
  11. });

The accessor nextResponders returns the list of responders of this in an array or initializes the list of responders of this with the array responders. IMPORTANT: nextResponders doesn't make a copy.

  1. Responder.prototype.addNextResponder = function(r) {
  2.     if (!( r instanceof Responder))
  3.         throw new TypeError();
  4.  
  5.     if (! this._nextResponders)
  6.         this._nextResponders = [r];
  7.     else if (this._nextResponders.indexOf(r) == -1)
  8.         this._nextResponders.push(r);
  9.  
  10.     return this;
  11. };

addNextResponder adds r to the list of responders of this.

  1. Responder.prototype.removeNextResponder = function(r) {
  2.     if (this._nextResponders) {
  3.         let i = this._nextResponders.indexOf(r);
  4.  
  5.         if (i != -1)
  6.             this._nextResponders.splice(i, 1);
  7.     }
  8.  
  9.     return this;
  10. };

removeNextResponder removes r from the list of responders of this.

  1. Responder.prototype.respondTo = function(f, ...args) {
  2.     if (typeof this[f] === 'function' && this[f](...args))
  3.         return this;
  4.  
  5.     if (! this._nextResponders)
  6.         return this;
  7.  
  8.     for (let r of this._nextResponders)
  9.         r.respondTo(f, ...args);
  10.  
  11.     return this;
  12. };

If this has the method f, respondTo executes f of this with args. If this doesn't have the method f or if the execution of f of this returns false, respondTo transmits the execution of f with args to all the instances in the list of responders of this.

  1. Responder.prototype.nextRespondTo = function(f, ...args) {
  2.     if (this._nextResponders)
  3.         for (let r of this._nextResponders)
  4.             r.respondTo(f, ...args);
  5.  
  6.     return this;
  7. };

nextRespondTo directly transmits the execution of f with args to all the instances in the list of responders of this.

Test
  1. <?php head('javascript', '/objectivejs/Objective.js'); ?>
  2. <?php head('javascript', '/objectivejs/Responder.js'); ?>

Adds the tags <script src="/objectivejs/Objective.js"></script> and <script src="/objectivejs/Responder.js"></script> to the <head> section of the HTML document.

  1. function X() {
  2.     Responder.call(this);
  3. }
  4.  
  5. X.prototype = Object.create(Responder.prototype);
  6.  
  7. Object.defineProperty(X.prototype, 'constructor', { value: X, enumerable: false, writable: true });
  8.  
  9. X.prototype.click = function() {
  10.     console.log('X clicked');
  11.  
  12.     this.respondTo('clicked', this);
  13. }
  14.  
  15. X.prototype.clicked = function(sender) {
  16.     console.log(this.constructor.name + ' received a click from ' + sender.constructor.name);
  17.  
  18.     return false;
  19. }

An instance of X is a Responder. The click method displays a trace message on the console and notifies clicked to this with this as a parameter, i.e. as the sender of the notification. The clicked method captures the clicked notification, displays a trace message on the console and returns false in order to transmit clicked to all the responders of this.

  1. function Y() {
  2.     Responder.call(this);
  3. }
  4.  
  5. Y.prototype = Object.create(Responder.prototype);
  6.  
  7. Object.defineProperty(Y.prototype, 'constructor', { value: Y, enumerable: false, writable: true });
  8.  
  9. Y.prototype.clicked = function(sender) {
  10.     console.log(this.constructor.name + ' received a click from ' + sender.constructor.name);
  11.  
  12.     return true;
  13. }

An instance of Y is a Responder. The click method displays a trace message on the console and notifies clicked to this with this as a parameter, i.e. as the sender of the notification. The clicked method captures the clicked notification, displays a trace message on the console and returns true in order to not transmit clicked to all the responders of this.

  1. function Z() {
  2.     Responder.call(this);
  3. }
  4.  
  5. Z.prototype = Object.create(Responder.prototype);
  6.  
  7. Object.defineProperty(Z.prototype, 'constructor', { value: Z, enumerable: false, writable: true });
  8.  
  9. Z.prototype.clicked = function(sender) {
  10.     console.log(this.constructor.name + ' received a click from ' + sender.constructor.name);
  11.  
  12.     return true;
  13. }

An instance of Z is a Responder. The click method displays a trace message on the console and notifies clicked to this with this as a parameter, i.e. as the sender of the notification. The clicked method captures the clicked notification, displays a trace message on the console and returns true in order to not transmit clicked to all the responders of this.

  1. var x = new X();
  2. var y = new Y();
  3. var z = new Z();

Creates an instance of X, of Y and of Z.

  1. x.click();

Clicks x which displays X clicked then responds to the message clicked by displaying X received a click from X.

  1. x.addNextResponder(y);
  2. x.click();

Adds y to the list of responders of x. Clicks x which displays X clicked, responds to the message clicked by displaying X received a click from X, then transmits the message clicked to y which displays Y received a click from X.

  1. delete X.prototype.clicked;
  2. x.click();

Removes the method clicked from the class X. Clicks x which displays X clicked then transmits the message clicked to y which displays Y received a click from X.

  1. x.addNextResponder(z);
  2. let responders = x.nextResponders;
  3. for (let r of responders)
  4.     console.log(r.constructor.name);
  5. x.nextResponders = null;
  6. console.log(x.nextResponders);
  7. x.nextResponders = responders;

Adds y to the list of responders of x. Displays the name of the class of all the responders of x. Empties the list of responders of x and displays it, i.e. null. Restores the list of responders of x.

  1. x.click();

Clicks x which displays X clicked and transmits the message clicked to y which displays Y received a click from X and to z which displays Z received a click from X.

  1. x.removeNextResponder(y);
  2. x.click();

Removes y from the list of responders of x. Clicks x which displays X clicked and transmits the message clicked to z which displays Z received a click from X.

  1. z.addNextResponder(y);
  2. x.click();

Adds y to the list of responders of z. Clicks x which displays X clicked and transmits the message clicked to z which displays Z received a click from X and doesn't transmit it to y.

Display the page generated by the file testResponder.phtml and check the trace in the console of the browser:

X clicked
X received a click from X
X clicked
X received a click from X
Y received a click from X
X clicked
Y received a click from X
Y
Z
null
X clicked
Y received a click from X
Z received a click from X
X clicked
Z received a click from X
X clicked
Z received a click from X

Modify the clicked method of the class Z so it returns false instead of true and reload the test page.

...
X clicked
Z received a click from X
Y received a click from X

z displays Z received a click from X and transmits the message clicked to y which displays Y received a click from X.

SEE ALSO

Objective, View

Comments

Your comment:
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip help 2000

Enter a maximum of 2000 characters.
Improve the presentation of your text with the following formatting tags:
[p]paragraph[/p], [b]bold[/b], [i]italics[/i], [u]underline[/u], [s]strike[/s], [quote]citation[/quote], [pre]as is[/pre], [br]line break,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]command[/code], [code=language]source code in c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].