blob: 7dcf4bd4a7da38cf71414c3f981e622b30af267b [file] [log] [blame]
genia.likes.science@gmail.comc5f82a22013-05-08 02:44:35 -07001/**
2 * easyXDM
3 * http://easyxdm.net/
4 * Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24/*jslint browser: true, immed: true, passfail: true, undef: true, newcap: true*/
25/*global easyXDM, window */
26/**
27 * easyXDM
28 * http://easyxdm.net/
29 * Copyright(c) 2009-2011, Øyvind Sean Kinsey, oyvind@kinsey.no.
30 *
31 * Permission is hereby granted, free of charge, to any person obtaining a copy
32 * of this software and associated documentation files (the "Software"), to deal
33 * in the Software without restriction, including without limitation the rights
34 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35 * copies of the Software, and to permit persons to whom the Software is
36 * furnished to do so, subject to the following conditions:
37 *
38 * The above copyright notice and this permission notice shall be included in
39 * all copies or substantial portions of the Software.
40 *
41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
44 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47 * THE SOFTWARE.
48 */
49/**
50 * @class easyXDM.WidgetManager
51 * A class for managing widgets.<br/>
52 * Handles initializing widgets, and does all of the message distribution.
53 <pre><code>
54 _widgetManager = new easyXDM.WidgetManager({
55 local: "../hash.html",
56 container: document.getElementById("defaultcontainer")
57 },function(){
58 _widgetManager.addWidget("http://provider.easyxdm.net/example/widget.html",{});
59 });
60 </code></pre>
61 * Widgets can by dynamically added using the addWidget method
62 <pre><code>
63 _widgetManager.addWidget("http://provider.easyxdm.net/example/widget.html",{
64 container document.getElementById("widgetcontainer")
65 });
66 </code></pre>
67 * @constructor
68 * @param {Object} config The WidgetManagers configuration
69 * @namespace easyXDM
70 */
71easyXDM.WidgetManager = function(config){
72 var WidgetManager = this, _hashUrl = config.local, _channelNr = 0;
73 var Events = {
74 WidgetInitialized: "widgetinitialized",
75 WidgetFailed: "widgetfailed"
76 };
77 var _widgets = {}, _subscribers = {};
78 var _widgetSettings = {
79 hosturl: location.href
80 };
81 easyXDM.apply(_widgetSettings, config.widgetSettings);
82 var _container = config.container || document.body;
83
84 /**
85 * @private
86 * Raises the specified event
87 * @param {String} event The raised event
88 * @param {Object} arg
89 */
90 function _raiseEvent(event, arg){
91 if (config.listeners && config.listeners[event]) {
92 config.listeners[event](WidgetManager, arg);
93 }
94 }
95
96 /**
97 * @private
98 * Adds the widghet to the list of subscribers for the given topic
99 * @param {String} url The widgets url
100 * @param {String} topic The topic to subscribe to
101 */
102 function _subscribe(url, topic){
103 if (!(topic in _subscribers)) {
104 _subscribers[topic] = [];
105 }
106 _subscribers[topic].push(url);
107 }
108
109 /**
110 * @private
111 * Initialized the widget.<br/>
112 * This is called after the widget has notified that it is ready.
113 * @param {Object} widget The widget
114 * @param {String} url The widgets url
115 * @param {Object} widgetConfig The widgets configuration
116 */
117 function _initializeWidget(widget, url, widgetConfig){
118 widget.initialize(_widgetSettings, function(response){
119 if (response.isInitialized) {
120 _widgets[url] = widget;
121 var i = response.subscriptions.length;
122 while (i--) {
123 _subscribe(url, response.subscriptions[i]);
124 }
125 _raiseEvent(Events.WidgetInitialized, {
126 url: url
127 });
128 }
129 else {
130 widget.destroy();
131 _raiseEvent(Events.WidgetFailed, {
132 url: url
133 });
134 }
135 });
136 }
137
138 /**
139 * @private
140 * Publishes the data to the topics subscribers
141 * @param {String} url The senders url
142 * @param {String} topic The datas topic
143 * @param {Object} data The data to publish
144 */
145 function _publish(url, topic, data){
146 var subscribers = _subscribers[topic];
147 if (subscribers) {
148 var i = subscribers.length, widgetUrl;
149 while (i--) {
150 widgetUrl = subscribers[i];
151 if (widgetUrl !== url) {
152 _widgets[widgetUrl].send(url, topic, data);
153 }
154 }
155 }
156 }
157
158 /**
159 * @private
160 * Sets up a new widget
161 * @param {String} url The widgets url
162 * @param {Object} widgetConfig The widgets configuration
163 */
164 function _setUpWidget(url, widgetConfig){
165 var widget = new easyXDM.Rpc({
166 channel: "widget" + _channelNr++,
167 local: _hashUrl,
168 remote: url,
169 container: widgetConfig.container || _container,
170 swf: config.swf,
171 onReady: function(){
172 _initializeWidget(widget, url, widgetConfig);
173 }
174 }, {
175 local: {
176 subscribe: {
177 isVoid: true,
178 method: function(topic){
179 _subscribe(url, topic);
180 }
181 },
182 publish: {
183 isVoid: true,
184 method: function(topic, data){
185 _publish(url, topic, data);
186 }
187 }
188 },
189 remote: {
190 initialize: {},
191 send: {
192 isVoid: true
193 }
194 }
195 });
196 }
197
198 /**
199 * Adds a widget to the collection
200 * @param {String} url The url to load the widget from
201 * @param {Object} widgetConfig The widgets url
202 */
203 this.addWidget = function(url, widgetConfig){
204 if (url in _widgets) {
205 throw new Error("A widget with this url has already been initialized");
206 }
207 _setUpWidget(url, widgetConfig);
208 };
209
210 /**
211 * Removes the widget
212 * @param {Object} url
213 */
214 this.removeWidget = function(url){
215 if (url in _widgets) {
216 for (var topic in _subscribers) {
217 if (_subscribers.hasOwnProperty(topic)) {
218 var subscribers = _subscribers[topic], i = subscribers.length;
219 while (i--) {
220 if (subscribers[i] === url) {
221 subscribers.splice(i, 1);
222 break;
223 }
224 }
225 }
226 }
227 _widgets[url].destroy();
228 delete _widgets[url];
229 }
230 };
231
232 /**
233 * Publish data to a topics subscribers
234 * @param {String} topic The topic to publish to
235 * @param {Object} data The data to publish
236 */
237 this.publish = function(topic, data){
238 _publish("", topic, data);
239 };
240
241 /**
242 * Broadcasts data to all the widgets
243 * @param {Object} data The data to broadcast
244 */
245 this.broadcast = function(data){
246 for (var url in _widgets) {
247 if (_widgets.hasOwnPropert(url)) {
248 _widgets[url].send({
249 url: "",
250 topic: "broadcast",
251 data: data
252 });
253 }
254 }
255 };
256};
257
258/**
259 * @class easyXDM.Widget
260 * The base framework for creating widgets
261 * @constructor
262 * @param {Object} config The widgets configuration
263 * @param {Function} onReady A method to run after the widget has been initialized.
264 * @namespace easyXDM
265 */
266easyXDM.Widget = function(config){
267 var _widget = this;
268 var _incomingMessageHandler;
269 var _widgetHost = new easyXDM.Rpc({
270 swf: config.swf
271 }, {
272 remote: {
273 subscribe: {
274 isVoid: true
275 },
276 publish: {
277 isVoid: true
278 }
279 },
280 local: {
281 initialize: {
282 method: function(settings){
283 config.initialized(_widget, _widgetHost);
284 return {
285 isInitialized: true,
286 subscriptions: config.subscriptions
287 };
288 }
289 },
290 send: {
291 isVoid: true,
292 method: function(url, topic, data){
293 _incomingMessageHandler(url, topic, data);
294 }
295 }
296 }
297 });
298
299 /**
300 * @private
301 * Destroy the interface on unload
302 */
303 window.onunload = function(){
304 _widgetHost.destroy();
305 };
306
307 /**
308 * Publish data to subscribers to a topic
309 * @param {String} topic The topic to publish to
310 * @param {Object} data The data to publish
311 */
312 this.publish = function(topic, data){
313 _widgetHost.publish(topic, data);
314 };
315
316 /**
317 * Subscribe to a topic
318 * @param {String} topic The topic to subscribe to
319 */
320 this.subscribe = function(topic){
321 _widgetHost.subscribe(topic);
322 };
323
324 /**
325 * Register the method that will handle incoming messages
326 * @param {Function} fn The handler
327 */
328 this.registerMessageHandler = function(fn){
329 _incomingMessageHandler = fn;
330 };
331
332 config.initialize(this, _widgetHost);
333};