(function(w) { if (w.fastXDM) return; var handlers = {}; var onEnvLoad = []; var env = {}; // Key generation function genKey() { var key = ''; for (i=0;i<5;i++) key += Math.ceil(Math.random()*15).toString(16); return key; } function waitFor(obj, prop, func, self, count) { if (obj[prop]) { func.apply(self); } else { count = count || 0; if (count < 1000) setTimeout(function() { waitFor(obj, prop, func, self, count + 1) }, 0); } } function attachScript(url) { setTimeout(function() { var newScript = document.createElement('script'); newScript.type = 'text/javascript'; newScript.src = url || w.fastXDM.helperUrl; waitFor(document, 'body', function() { document.getElementsByTagName('HEAD')[0].appendChild(newScript); }); }, 0); } // Env functions function getEnv(callback, self) { if (env.loaded) { callback.apply(self, [env]); } else { onEnvLoad.push([self, callback]); } } function envLoaded() { env.loaded = true; var i = onEnvLoad.length; while (i--) { onEnvLoad[i][1].apply(onEnvLoad[i][0], [env]); } } function applyMethod(strData, self) { getEnv(function(env) { var data = env.json.parse(strData); if (data[0]) { if (!data[1]) data[1] = []; var i = data[1].length; while (i--) { if (data[1][i]._func) { var funcNum = data[1][i]._func; data[1][i] = function() { var args = Array.prototype.slice.call(arguments); args.unshift('_func'+funcNum); self.callMethod.apply(self, args); } } } setTimeout(function() { if (!self.methods[data[0]]) throw Error('fastXDM: Method ' + data[0] + ' is undefined'); self.methods[data[0]].apply(self, data[1]); }, 0); } }); } // XDM object w.fastXDM = { _id: 0, helperUrl: 'http://userapi.com/js/api/xdmHelper.js?2', Server: function(methods, filter) { this.methods = methods || {}; this.id = w.fastXDM._id++; this.filter = filter; this.key = genKey(); this.methods['%init%'] = this.methods['__fxdm_i'] = function() { w.fastXDM.run(this.id); if (this.methods['onInit']) this.methods['onInit'](); }; this.frameName = 'fXD'+this.key; this.server = true; handlers[this.key] = [applyMethod, this]; }, Client: function(methods) { this.methods = methods || {}; this.id = w.fastXDM._id++; w.fastXDM.run(this.id); if (window.name.indexOf('fXD') == 0) { this.key = window.name.substr(3); } else { throw Error('Wrong window.name property.'); } this.caller = window.parent; handlers[this.key] = [applyMethod, this]; this.client = true; w.fastXDM.on('helper', function() { w.fastXDM.onClientStart(this); }, this); getEnv(function(env) { env.send(this, env.json.stringify(['%init%'])); var methods = this.methods; setTimeout(function() { if (methods['onInit']) methods['onInit'](); }, 0); }, this); }, onMessage: function(e) { if (!e.data) return false; var key = e.data.substr(0, 5); if (handlers[key]) { var self = handlers[key][1]; if (self && (!self.filter || self.filter(e.origin))) { handlers[key][0](e.data.substr(6), self); } } }, setJSON: function(json) { env.json = json; }, getJSON: function(callback) { if (!callback) return env.json; getEnv(function(env) { callback(env.json); }); }, setEnv: function(exEnv) { for (i in exEnv) { env[i] = exEnv[i]; } envLoaded(); }, _q: {}, on: function(key, act, self) { if (!this._q[key]) this._q[key] = []; if (this._q[key] == -1) { act.apply(self); } else { this._q[key].push([act, self]); } }, run: function(key) { var len = (this._q[key] || []).length; if (this._q[key] && len > 0) { for (var i = 0; i < len; i++) this._q[key][i][0].apply(this._q[key][i][1]); } this._q[key] = -1; }, waitFor: waitFor } w.fastXDM.Server.prototype.start = function(obj, count) { if (obj.contentWindow) { this.caller = obj.contentWindow; this.frame = obj; w.fastXDM.on('helper', function() { w.fastXDM.onServerStart(this); }, this); } else { // Opera old versions var self = this; count = count || 0; if (count < 50) setTimeout(function() { self.start.apply(self, [obj, count+1]); }, 100); } } function extend(obj1, obj2){ for (var i in obj2) { if (obj1[i] && typeof(obj1[i]) == 'object') { extend(obj1[i], obj2[i]) } else { obj1[i] = obj2[i]; } } } w.fastXDM.Server.prototype.append = function(obj, options) { var div = document.createElement('DIV'); div.innerHTML = '