/[meteor]/googlecode.com/svn/trunk/public_html/meteor.js
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /googlecode.com/svn/trunk/public_html/meteor.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (show annotations)
Tue Nov 21 09:49:07 2006 UTC (17 years, 4 months ago) by andrew.betts
File MIME type: application/javascript
File size: 8752 byte(s)
changed line endings

1 // Set domain at highest level
2 var domainparts = document.domain.split(".");
3 document.domain = domainparts[domainparts.length-2]+"."+domainparts[domainparts.length-1];
4
5 Function.prototype.bind = function(obj) {
6 var method = this,
7 temp = function() {
8 return method.apply(obj, arguments);
9 };
10 return temp;
11 }
12 Function.prototype.andThen=function(g) {
13 var f=this;
14 var a=this.arguments
15 return function(args) {
16 f(a);g(args);
17 }
18 };
19
20 function Meteor(instID) {
21
22 this.lastmsgreceived = -1;
23 this.transferDoc = false;
24 this.pingtimer = false;
25 this.updatepollfreqtimer = false;
26 this.lastrequest = 0;
27 this.recvtimes = new Array();
28 this.MHostId = false;
29 this.callback_process = function() {};
30 this.callback_reset = function() {};
31 this.callback_eof = function() {};
32 this.callback_changemode = function() {};
33 this.persist = true;
34
35 // Documented public properties
36 this.channel = false;
37 this.subdomain = "data";
38 this.dynamicpageaddress = "push";
39 this.backtrack = 0;
40 this.smartpoll = true;
41 this.pollfreq = 2000;
42 this.minpollfreq = 2000;
43 this.mode = "stream";
44 this.polltimeout=30000;
45 this.maxmessages=0;
46 this.pingtimeout = 10000;
47
48 // Set or retrieve host id. Cookie takes this form:
49 // MeteorID=123:6356353/124:098320454;
50 var MeteIds = Meteor.readCookie("MeteorID");
51 var regex1 = new RegExp("^([0-9\:\/M]+\/)*"+instID+"\:([^\/]+)(\/[0-9\:\/M]+)*$");
52 var regex2 = new RegExp("^([0-9\:\/M]+\/)*M\:([^\/]+)(\/[0-9\:\/M]+)*$");
53 if (typeof(instID) == "Number" && regex1.exec(MeteIds)) {
54 this.MHostId = ma[2];
55 } else if (typeof(instID) == "Number") {
56 this.MHostId = Math.floor(Math.random()*1000000);
57 var newcookie = (MeteIds)?MeteIds+"/":"";
58 newcookie += instID+":"+this.MHostId;
59 Meteor.createCookie("MeteorID", newcookie);
60 } else if (ma = regex2.exec(MeteIds)) {
61 this.MHostId = ma[2];
62 } else {
63 this.MHostId = Math.floor(Math.random()*1000000);
64 var newcookie = (MeteIds)?MeteIds+"/":"";
65 newcookie += "M:"+this.MHostId;
66 Meteor.createCookie("MeteorID", newcookie);
67 }
68 this.instID = (typeof(instID) != "undefined") ? instID : 0;
69 }
70
71 Meteor.instances = new Array();
72 Meteor.servertimeoffset = 0;
73
74 Meteor.create = function(instID) {
75 if (!instID) instID = 0;
76 Meteor.instances[instID] = new Meteor(instID);
77 return Meteor.instances[instID];
78 }
79
80 Meteor.register = function(ifr) {
81 instid = new String(ifr.window.frameElement.id);
82 instid = instid.replace("meteorframe_", "");
83 ifr.p = this.instances[instid].process.bind(this.instances[instid]);
84 ifr.r = this.instances[instid].reset.bind(this.instances[instid]);
85 ifr.eof = this.instances[instid].eof.bind(this.instances[instid]);
86 ifr.get = this.instances[instid].get.bind(this.instances[instid]);
87 ifr.increasepolldelay = this.instances[instid].increasepolldelay.bind(this.instances[instid]);
88 }
89
90 Meteor.setServerTime = function(timestamp) {
91 var now = new Date();
92 var clienttime = (now.getTime() / 1000);
93 Meteor.servertimeoffset = timestamp - clienttime;
94 }
95
96 Meteor.prototype.start = function() {
97 this.persist = (this.maxmessages)?1:0;
98 this.smartpoll = (this.smartpoll)?1:0;
99 this.mode = (this.mode=="stream")?"stream":"poll";
100 if (!this.subdomain || !this.channel) throw "Channel or Meteor subdomain host not specified";
101 var now = new Date();
102 var t = now.getTime();
103 if (typeof(this.transferDoc)=="object") {
104 this.transferDoc.open();
105 this.transferDoc.close();
106 delete this.transferDoc;
107 }
108 if (document.getElementById("meteorframe_"+this.instID)) {
109 document.body.removeChild(document.getElementById("meteorframe_"+this.instID));
110 }
111 if (this.mode=="stream") {
112 if (document.all) {
113 this.transferDoc = new ActiveXObject("htmlfile");
114 this.transferDoc.open();
115 this.transferDoc.write("<html>");
116 this.transferDoc.write("<script>document.domain=\""+(document.domain)+"\";</"+"script>");
117 this.transferDoc.write("</html>");
118 var selfref = this;
119 this.transferDoc.parentWindow.Meteor = Meteor;
120 this.transferDoc.close();
121 var ifrDiv = this.transferDoc.createElement("div");
122 this.transferDoc.appendChild(ifrDiv);
123 var url = "http://"+this.subdomain+"."+location.hostname+"/"+this.dynamicpageaddress+"?channel="+this.channel+"&id="+this.MHostId;
124 if (this.lastmsgreceived >= 0) {
125 url += "&restartfrom="+this.lastmsgreceived;
126 } else if (this.backtrack > 0) {
127 url += "&backtrack="+this.backtrack;
128 } else if (this.backtrack < 0 || isNaN(this.backtrack)) {
129 url += "&restartfrom=";
130 }
131 ifrDiv.innerHTML = "<iframe id=\"meteorframe_"+this.instID+"\" src=\""+url+"&nocache="+t+"\" style=\"display: none;\"></iframe>";
132 } else {
133 var ifr = document.createElement("IFRAME");
134 ifr.style.width = "10px";
135 ifr.style.height = "10px";
136 ifr.style.border = "none";
137 ifr.style.position = "absolute";
138 ifr.style.top = "-10px";
139 ifr.style.marginTop = "-10px";
140 ifr.style.zIndex = "-20";
141 ifr.id = "meteorframe_"+this.instID;
142 document.body.appendChild(ifr);
143 ifr.src = "http://"+this.subdomain+"."+location.hostname+"/stream.html?nocache="+t;
144 }
145 var f = this.pollmode.bind(this);
146 clearTimeout(this.pingtimer);
147 this.pingtimer = setTimeout(f, this.pingtimeout);
148
149 } else {
150 var ifr = document.createElement("IFRAME");
151 ifr.style.width = "10px";
152 ifr.style.height = "10px";
153 ifr.style.border = "none";
154 if (document.all) {
155 ifr.style.display = "none";
156 } else {
157 ifr.style.position = "absolute";
158 ifr.style.marginTop = "-10px";
159 ifr.style.zIndex = "-20";
160 }
161 ifr.id = "meteorframe_"+this.instID;
162 document.body.appendChild(ifr);
163 ifr.src = "http://"+this.subdomain+"."+location.hostname+"/poll.html?nocache="+t;
164 this.recvtimes[0] = t;
165 if (this.updatepollfreqtimer) clearTimeout(this.updatepollfreqtimer);
166 this.updatepollfreqtimer = setInterval(this.updatepollfreq.bind(this), 2500);
167 }
168 this.lastrequest = t;
169 }
170
171 Meteor.prototype.pollmode = function() {
172 this.mode="poll";
173 this.start();
174 this.callback_changemode("poll");
175 }
176
177 Meteor.prototype.process = function(id, data) {
178 if (id > this.lastmsgreceived) {
179 this.callback_process(data);
180 if (id != -1) this.lastmsgreceived = id;
181 if (this.mode=="poll") {
182 var now = new Date();
183 var t = now.getTime();
184 this.recvtimes[this.recvtimes.length] = t;
185 while (this.recvtimes.length > 5) this.recvtimes.shift();
186 }
187 } else if (id == -1) {
188 this.ping();
189 }
190 }
191
192 Meteor.prototype.ping = function() {
193 if (this.mode=="stream" && this.pingtimer) {
194 clearTimeout(this.pingtimer);
195 var f = this.pollmode.bind(this);
196 this.pingtimer = setTimeout(f, this.pingtimeout);
197 var now = new Date();
198 this.lastpingtime = now.getTime();
199 }
200 }
201
202 Meteor.prototype.reset = function() {
203 var now = new Date();
204 var t = now.getTime();
205 var x = this.pollfreq - (t-this.lastrequest);
206 if (x < 10) x = 10;
207 this.ping();
208 this.callback_reset();
209 setTimeout(this.start.bind(this), x);
210 }
211
212 Meteor.prototype.eof = function() {
213 this.callback_eof();
214 }
215
216 Meteor.prototype.get = function(varname) {
217 eval("var a = this."+varname+";");
218 if (typeof(a) == "undefined") throw "Cannot get value of "+varname;
219 return a;
220 }
221
222 Meteor.prototype.increasepolldelay = function() {
223 this.pollfreq *= 2;
224 }
225
226 Meteor.prototype.updatepollfreq = function() {
227 if (this.smartpoll) {
228 var now = new Date();
229 var t = now.getTime();
230 var avg = 0;
231 for (var i=1; i<this.recvtimes.length; i++) {
232 var x = (this.recvtimes[i]-this.recvtimes[i-1]);
233 avg += (x>60000)? 60000 : x;
234 }
235 x = (t-this.recvtimes[this.recvtimes.length-1]);
236 avg += (x>180000)? 180000 : x;
237 avg /= this.recvtimes.length;
238 if ((avg/3) < this.pollfreq && (avg/3) >= this.minpollfreq) this.pollfreq = Math.ceil(this.pollfreq*0.9);
239 if ((avg/3) > this.pollfreq) this.pollfreq = Math.floor(this.pollfreq*1.05);
240 }
241 }
242
243 Meteor.prototype.registerEventCallback = function(evt, funcRef) {
244 if (evt=="process") {
245 this.callback_process = (this.callback_process).andThen(funcRef);
246 } else if (evt=="reset") {
247 this.callback_reset = (this.callback_reset).andThen(funcRef);
248 } else if (evt=="eof") {
249 this.callback_eof = (this.callback_eof).andThen(funcRef);
250 } else if (evt=="changemode") {
251 this.callback_changemode = (this.callback_changemode).andThen(funcRef);
252 }
253 }
254
255
256 Meteor.createCookie = function(name,value,days) {
257 if (days) {
258 var date = new Date();
259 date.setTime(date.getTime()+(days*24*60*60*1000));
260 var expires = "; expires="+date.toGMTString();
261 }
262 else var expires = "";
263 document.cookie = name+"="+value+expires+"; path=/";
264 }
265
266 Meteor.readCookie = function(name) {
267 var nameEQ = name + "=";
268 var ca = document.cookie.split(';');
269 for(var i=0;i < ca.length;i++) {
270 var c = ca[i];
271 while (c.charAt(0)==' ') c = c.substring(1,c.length);
272 if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
273 }
274 return null;
275 }
276
277 Meteor.eraseCookie = function(name) {
278 createCookie(name,"",-1);
279 }

  ViewVC Help
Powered by ViewVC 1.1.26