window.urb.seqn_u = 1 window.urb.dely = 0 window.urb.puls = false window.urb.cabs = {} if(!window.urb.appl) window.urb.appl = null window.urb.req = function(method,url,params,json,cb) { var xhr = new XMLHttpRequest() method = method.toUpperCase() if(method == "PUT" || method == "DELETE") xhr.open("POST", url+"?"+method) else xhr.open(method, url) if(json) xhr.setRequestHeader("content-type", "text/json") if(!window.urb.oryx) throw "No CSRF token" // XX fetch auth.json _data = {oryx: window.urb.oryx} if(params.xyro) { _data.xyro = params.xyro; } if(params.ship) { _data.ship = params.ship; } if(params.path) { _data.path = params.path; } if(params.appl) { _data.appl = params.appl; } if(params.mark) { _data.mark = params.mark; } if(params.wire) { _data.wire = params.wire; } if(cb) { xhr.onload = function() { try { err = null res = { status:this.status, data: JSON.parse(this.responseText) } if(res.data.reload) res.reload = res.data.reload } catch(e) { if(urb.wall !== false) document.write(this.responseText) // XX err = { message:"Failed to parse JSON", raw:this.responseText } res = null } cb(err,res) } xhr.onerror = function() { cb({ status:this.status, data:this.responseText }) } } xhr.send(JSON.stringify(_data)) } // window.urb.getJSON = function(url,cb){ window.urb.reqJSON("GET",url, null, cb)} // window.urb.reqJSON = function(method, url, data, cb){ // var xhr = new XMLHttpRequest() // xhr.open(method, url) // xhr.onload = function(){ // urb.fetchTag.call(xhr) // if(cb) cb(JSON.parse(xhr.responseText)) // } // xhr.send(data === null ? null : JSON.stringify(data)) // } window.urb.reqq = [] window.urb.qreq = function(method,url,params,json,cb) { walk = function() { qobj = {} qobj.oargs = window.urb.reqq[0] qobj.nargs = [].slice.apply(qobj.oargs,[0,4]) qobj.nargs.push(function(){ if(this.oargs[4]) this.oargs[4].apply(window.urb,arguments) window.urb.reqq.shift() if(window.urb.reqq.length > 0) walk() }.bind(qobj)) window.urb.req.apply(this,qobj.nargs) } l = window.urb.reqq.length window.urb.reqq.push(arguments); if(l == 0) { walk() } } window.urb.gsig = function(params) { var path = params.path if(!path) path = "" if(path[0] !== "/") path = "/"+path return "~"+params.ship+"/"+ params.appl+ path.replace(/[^\x00-\x7F]/g, "") } window.urb.poll = function(params) { if(!params) throw new Error("You must supply params to urb.poll.") var url, $this seqn = this.seqn_u if(params.seqn) seqn = params.seqn() url = "/~/of/"+this.ixor+"?poll="+seqn this.puls = true $this = this this.req("get",url,params,true,function(err,res) { if(res){ if(res.data.beat) return $this.poll(params) switch(res.data.type){ case "news": return document.location.reload() // XX check autoreload case "rush": case "mean": var err2 = err if(res.data.type == "mean") err2 = res.data.data var fn = $this.gsig(res.data.from) if($this.cabs[fn]) $this.cabs[fn].call(this,err2, {status: res.status, data: res.data.data.json}) // XX non-json break; default: throw new Error("Lost event %"+res.data.type) } } dely = params.dely ? params.dely : $this.dely if(err) dely = dely+Math.ceil(dely*.02) else { $this.dely = 0 if(params.incs) params.incs() else $this.seqn_u++ } setTimeout(function() { $this.poll(params) },dely) }) } // if (window.urb.auto) { // need dependencies // var tries = 0 // var cnt = 0 // var param = { // type:"pol" // } // window.urb.poll(param) // } // window.urb.heartbeat = function() { // this.poll({ // type:"heb", // ship:this.ship, // dely:30000, // seqn:function() { // return window.urb.seqn_h // }, // incs:function() { // window.urb.seqn_h = window.urb.seqn_h+1 // } // },function() { // console.log('heartbeat.') // }) // } // window.urb.heartbeat() // // / // / // // // end old %eyre code // // // / // / // // window.urb.seqn_s = 0 // TODO urb.send(data, [params/params.appl]?, cb?) window.urb.send = function(params,cb) { if(!params) throw new Error("You must supply params to urb.send.") if(!params.appl && !this.appl){ throw new Error("You must specify an appl for urb.send.") } var url, $this params.ship = params.ship ? params.ship : this.ship params.appl = params.appl ? params.appl : this.appl params.mark = params.mark ? params.mark : "json" params.xyro = params.data ? params.data : {} params.wire = params.wire ? params.wire : "/" url = ["to",params.appl,params.mark] url = "/~/"+url.join("/") this.seqn_s++ $this = this this.qreq('post',url,params,true,function(err,data) { if(err) { $this.seqn_s--; } if(cb) { cb.apply(this,arguments); } }) } window.urb.subscribe = function(params,cb) { // legacy interface if(!params) throw new Error("You must supply params to urb.subscribe") return window.urb.bind(params.path, params, cb, cb) } window.urb.bind = function(path, cb){ // or bind(path, params, cb, nicecb?) var params, nicecb if(arguments.length > 2) {params = cb; cb = arguments[2], nicecb = arguments[3]} else params = {} params.path = path if(params.path[0] !== "/") params.path = "/"+params.path params.ship = params.ship ? params.ship : this.ship params.appl = params.appl ? params.appl : this.appl params.mark = params.mark ? params.mark : "json" params.wire = params.wire ? params.wire : params.path if(typeof path != "string") throw new Error("You must specify a string path for urb.bind.") if(!params.appl) throw new Error("You must specify an appl for urb.bind.") if(!cb) throw new Error("You must supply a callback to urb.bind.") var method, perm, url, $this if(params.mark !== "json") throw new Error("Non-json subscriptions unimplemented.") // XX url = "/~/is/"+this.gsig(params)+"."+params.mark params.path = params.wire this.cabs[this.gsig(params)] = cb $this = this this.qreq("put",url,params,true,function(err,res) { if(nicecb) { nicecb.apply(this,[err,{status: res.status, data: res.data}])} // XX give raw data // if(!err && !$this.puls) $this.poll(params) }) } window.urb.unsubscribe = function(params,cb) { if(!params) throw new Error("You must supply params to urb.unsubscribe.") params.ship = params.ship ? params.ship : this.ship params.appl = params.appl ? params.appl : this.appl params.wire = params.wire ? params.wire : params.path if(!params.path) throw new Error("You must specify a path for urb.unsubscribe.") if(!params.appl) throw new Error("You must specify an appl for urb.unsubscribe.") url = "/~/is/"+this.gsig(params)+".json" method = "delete" this.req("delete",url,params,true,function(err,res) { if(cb) cb(err,res) }) } window.urb.util = { isURL: function(s) { r = new RegExp('^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$', 'i'); return s.length < 2083 && r.test(s); }, numDot: function(n) { _n = String(n) fun = function(s){ if(s.length <= 3) return s return fun(s.slice(0,-3))+"."+s.slice(-3) } return fun((_n)) }, toDate: function (dat){ var mils = Math.floor((0x10000 * dat.getUTCMilliseconds()) / 1000).toString(16) function pad(num, str){ return ((new Array(num + 1)).join('0') + str).substr(-num,num) } return '~' + dat.getUTCFullYear() + '.' + (dat.getUTCMonth() + 1) + '.' + dat.getUTCDate() + '..' + pad(2, dat.getUTCHours()) + '.' + pad(2, dat.getUTCMinutes()) + '.' + pad(2, dat.getUTCSeconds()) + '..' + pad(4, mils) } }