1 /**
  2  * @fileOverview
  3  * telepathy.enchant.js
  4  * @version 0.1.0
  5  * @require enchant.js v0.8.0+
  6  * @author UEI Corporation
  7  */
  8 (function() {
  9 /**
 10  * @namespace enchant.telepathy
 11  */
 12 enchant.telepathy = {};
 13 
 14 /**
 15  * @type String
 16  */
 17 enchant.telepathy.SEND_API_URL = 'http://skylab.enchantmoon.com/moonblock/add_data/';
 18 /**
 19  * @type String
 20  */
 21 enchant.telepathy.RECV_API_URL = 'http://skylab.enchantmoon.com/moonblock/watch/';
 22 
 23 /**
 24  * @type String
 25  */
 26 enchant.Event.TELEPATHY = 'telepathy';
 27 
 28 /**
 29  * @scope enchant.telepathy.Telepathy.prototype
 30  */
 31 enchant.telepathy.Telepathy = enchant.Class.create(enchant.Event, {
 32     /**
 33      * @name enchant.telepathy.Telepathy
 34      * @class
 35      * @constructs
 36      * @extends enchant.Event
 37      */
 38     initialize: function(channel, data) {
 39         enchant.Event.call(this, enchant.Event.TELEPATHY);
 40 
 41         /**
 42          * @type String
 43          */
 44         this.channel = channel;
 45         /**
 46          * @type *
 47          */
 48         this.data = data;
 49     }
 50 });
 51 
 52 /**
 53  * @scope enchant.telepathy.TelepathySense.prototype
 54  */
 55 enchant.telepathy.TelepathySense = enchant.Class.create(enchant.EventTarget, {
 56     /**
 57      * @name enchant.telepathy.TelepathySense
 58      * @class
 59      * @construct
 60      * @extends enchant.EventTarget
 61      */
 62     initialize: function() {
 63         enchant.EventTarget.call(this);
 64 
 65         /**
 66          * @type Object
 67          */
 68         this.channelers = {};
 69         /**
 70          * @type Object
 71          */
 72         this.eventSources = {};
 73         /**
 74          * @type enchant.telepathy.Telepathy
 75          */
 76         this.lastTelepathy = null;
 77         /**
 78          * @type String
 79          */
 80         this.sendAPI = enchant.telepathy.SEND_API_URL;
 81         /**
 82          * @type String
 83          */
 84         this.recvAPI = enchant.telepathy.RECV_API_URL;
 85 
 86         this.addEventListener(enchant.Event.TELEPATHY, this._ontelepathy);
 87     },
 88     /**
 89      * @param {enchant.Event} evt
 90      * @private
 91      */
 92     _ontelepathy: function(evt) {
 93         var i, l,
 94             channelers = this.channelers[evt.channel];
 95 
 96         this.lastTelepathy = evt;
 97 
 98         if (!channelers) {
 99             return;
100         }
101 
102         for (i = 0, l = channelers.length; i < l; i++) {
103             channelers[i].dispatchEvent(evt);
104         }
105     },
106     /**
107      */
108     addChanneler: function(channel, target) {
109         if (this.channelers[channel]) {
110             if (this.channelers[channel].indexOf(target) === -1) {
111                 this.channelers[channel].push(target);
112             }
113         } else {
114             this.channelers[channel] = [ target ];
115         }
116     },
117     /**
118      */
119     removeChanneler: function(channel, target) {
120         var i;
121 
122         if (!this.channelers[channel]) {
123             return;
124         }
125 
126         i = this.channelers[channel].indexOf(target);
127 
128         if (i !== -1) {
129             this.channelers[channel].splice(i, 1);
130         }
131     },
132     /**
133      */
134     send: function(channel, message) {
135         var xhr = new XMLHttpRequest(),
136             data = JSON.stringify({ value: message });
137 
138         xhr.open('POST', this.sendAPI + channel, true);
139         xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
140         xhr.addEventListener('error', function(evt) {
141             var errorEvent = new enchant.Event(enchant.Event.ERROR);
142             errorEvent.message = 'Cannot send telepathy: ' + channel;
143             this.dispatchEvent(errorEvent);
144         }.bind(this));
145         xhr.send('object=' + data);
146     },
147     /**
148      */
149     open: function(channel) {
150         var eventSource = new EventSource(this.recvAPI + channel);
151 
152         eventSource.addEventListener('message', function(evt) {
153             var i, l,
154                 data = JSON.parse(evt.data),
155                 stream = data.objects;
156 
157             for (i = 0, l = stream.length; i < l; i++) {
158                 this.dispatchEvent(new enchant.telepathy.Telepathy(channel, JSON.parse(stream[i]).value));
159             }
160         }.bind(this));
161 
162         this.eventSources[channel] = eventSource;
163     },
164     /**
165      */
166     close: function(channel) {
167         var eventSource = this.eventSources[channel];
168 
169         if (eventSource) {
170             eventSource.close();
171             delete this.eventSources[channel];
172             delete this.channelers[channel];
173         }
174     },
175     /**
176      */
177     closeAll: function() {
178         for (var channel in this.eventSources) {
179             this.close(channel);
180         }
181     },
182     /**
183      */
184     finalize: function() {
185         this.clearEventListener();
186         this.closeAll();
187         this.channelers = {};
188     }
189 });
190 
191 }());
192