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 * デフォルトの送信APIのURL. 16 * @type String 17 */ 18 enchant.telepathy.SEND_API_URL = 'http://skylab.enchantmoon.com/moonblock/add_data/'; 19 /** 20 * デフォルトの受信APIのURL. 21 * @type String 22 */ 23 enchant.telepathy.RECV_API_URL = 'http://skylab.enchantmoon.com/moonblock/watch/'; 24 25 /** 26 * オブジェクトににアプリケーション外からのメッセージ(テレパシー)を与えるイベント. 27 * 発行するオブジェクト: {@link enchant.telepathy.TelepathySence} 28 * @type String 29 */ 30 enchant.Event.TELEPATHY = 'telepathy'; 31 32 /** 33 * @scope enchant.telepathy.Telepathy.prototype 34 */ 35 enchant.telepathy.Telepathy = enchant.Class.create(enchant.Event, { 36 /** 37 * @name enchant.telepathy.Telepathy 38 * @class 39 * アプリケーション外からのメッセージを表すイベントオブジェクト. 40 * @param {String} channel チャンネル. 41 * @param {*} data データ. 42 * @constructs 43 * @extends enchant.Event 44 */ 45 initialize: function(channel, data) { 46 enchant.Event.call(this, enchant.Event.TELEPATHY); 47 48 /** 49 * テレパシーのチャンネルを表す. 50 * @type String 51 */ 52 this.channel = channel; 53 /** 54 * テレパシーの内容を表す. 55 * @type * 56 */ 57 this.data = data; 58 } 59 }); 60 61 /** 62 * @scope enchant.telepathy.TelepathySense.prototype 63 */ 64 enchant.telepathy.TelepathySense = enchant.Class.create(enchant.EventTarget, { 65 /** 66 * @name enchant.telepathy.TelepathySense 67 * @class 68 * テレパシーの送受信を行うためのオブジェクト. 69 * @construct 70 * @extends enchant.EventTarget 71 */ 72 initialize: function() { 73 enchant.EventTarget.call(this); 74 75 /** 76 * Telepathyの受信者を保持するオブジェクト. 77 * @type Object 78 */ 79 this.channelers = {}; 80 /** 81 * Telepathyの受信に使用するEventSourceを保持するオブジェクト. 82 * @type Object 83 */ 84 this.eventSources = {}; 85 /** 86 * 最後に受信したTelepathyオブジェクト. 87 * @type enchant.telepathy.Telepathy 88 */ 89 this.lastTelepathy = null; 90 /** 91 * テレパシー送信APIのURL. 92 * @type String 93 */ 94 this.sendAPI = enchant.telepathy.SEND_API_URL; 95 /** 96 * テレパシー受信APIのURL. 97 * @type String 98 */ 99 this.recvAPI = enchant.telepathy.RECV_API_URL; 100 101 this.addEventListener(enchant.Event.TELEPATHY, this._ontelepathy); 102 }, 103 /** 104 * @param {enchant.Event} evt 105 * @private 106 */ 107 _ontelepathy: function(evt) { 108 var i, l, 109 channelers = this.channelers[evt.channel]; 110 111 this.lastTelepathy = evt; 112 113 if (!channelers) { 114 return; 115 } 116 117 for (i = 0, l = channelers.length; i < l; i++) { 118 channelers[i].dispatchEvent(evt); 119 } 120 }, 121 /** 122 * オブジェクトをTelepathyの受信者に設定する. 123 * @param {String} channel 対象のチャンネル. 124 * @param {enchant.EventTarget} target 対象のオブジェクト. 125 */ 126 addChanneler: function(channel, target) { 127 if (this.channelers[channel]) { 128 if (this.channelers[channel].indexOf(target) === -1) { 129 this.channelers[channel].push(target); 130 } 131 } else { 132 this.channelers[channel] = [ target ]; 133 } 134 }, 135 /** 136 * オブジェクトをTelepathyの受信者から除外する. 137 * @param {String} channel 対象のチャンネル. 138 * @param {enchant.EventTarget} target 対象のオブジェクト. 139 */ 140 removeChanneler: function(channel, target) { 141 var i; 142 143 if (!this.channelers[channel]) { 144 return; 145 } 146 147 i = this.channelers[channel].indexOf(target); 148 149 if (i !== -1) { 150 this.channelers[channel].splice(i, 1); 151 } 152 }, 153 /** 154 * テレパシーを送信する. 155 * @param {String} channel 対象のチャンネル. 156 * @param {*} message 送信するデータ. 157 */ 158 send: function(channel, message) { 159 var xhr = new XMLHttpRequest(), 160 data = JSON.stringify({ value: message }); 161 162 xhr.open('POST', this.sendAPI + channel, true); 163 xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 164 xhr.addEventListener('error', function(evt) { 165 var errorEvent = new enchant.Event(enchant.Event.ERROR); 166 errorEvent.message = 'Cannot send telepathy: ' + channel; 167 this.dispatchEvent(errorEvent); 168 }.bind(this)); 169 xhr.send('object=' + data); 170 }, 171 /** 172 * テレパシーの受信を開始する. 173 * @param {String} channel 対象のチャンネル. 174 */ 175 open: function(channel) { 176 var eventSource = new EventSource(this.recvAPI + channel); 177 178 eventSource.addEventListener('message', function(evt) { 179 var i, l, 180 data = JSON.parse(evt.data), 181 stream = data.objects; 182 183 for (i = 0, l = stream.length; i < l; i++) { 184 this.dispatchEvent(new enchant.telepathy.Telepathy(channel, JSON.parse(stream[i]).value)); 185 } 186 }.bind(this)); 187 188 this.eventSources[channel] = eventSource; 189 }, 190 /** 191 * テレパシーの受信を終了する. 192 * @param {String} channel 対象のチャンネル. 193 */ 194 close: function(channel) { 195 var eventSource = this.eventSources[channel]; 196 197 if (eventSource) { 198 eventSource.close(); 199 delete this.eventSources[channel]; 200 delete this.channelers[channel]; 201 } 202 }, 203 /** 204 * 全てのチャンネルについてテレパシーの受信を終了する. 205 */ 206 closeAll: function() { 207 for (var channel in this.eventSources) { 208 this.close(channel); 209 } 210 }, 211 /** 212 * TelepathySenseの後処理を行う. 213 */ 214 finalize: function() { 215 this.clearEventListener(); 216 this.closeAll(); 217 this.channelers = {}; 218 } 219 }); 220 221 }()); 222