Massive directory cleanup, more reliable transport

This commit is contained in:
Mark Nadal 2014-12-06 15:26:00 -08:00
parent f27f330131
commit 221b9385d7
68 changed files with 3015 additions and 1554550 deletions

View File

@ -1,3 +0,0 @@
For information about action hooks supported by OpenShift, consult the documentation:
http://openshift.github.io/documentation/oo_user_guide.html#the-openshift-directory

View File

@ -1,23 +0,0 @@
Run scripts or jobs on a periodic basis
=======================================
Any scripts or jobs added to the minutely, hourly, daily, weekly or monthly
directories will be run on a scheduled basis (frequency is as indicated by the
name of the directory) using run-parts.
run-parts ignores any files that are hidden or dotfiles (.*) or backup
files (*~ or *,) or named *.{rpmsave,rpmorig,rpmnew,swp,cfsaved}
The presence of two specially named files jobs.deny and jobs.allow controls
how run-parts executes your scripts/jobs.
jobs.deny ===> Prevents specific scripts or jobs from being executed.
jobs.allow ===> Only execute the named scripts or jobs (all other/non-named
scripts that exist in this directory are ignored).
The principles of jobs.deny and jobs.allow are the same as those of cron.deny
and cron.allow and are described in detail at:
http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/ch-Automating_System_Tasks.html#s2-autotasks-cron-access
See: man crontab or above link for more details and see the the weekly/
directory for an example.
PLEASE NOTE: The Cron cartridge must be installed in order to run the configured jobs.

View File

View File

View File

View File

View File

@ -1,16 +0,0 @@
Run scripts or jobs on a weekly basis
=====================================
Any scripts or jobs added to this directory will be run on a scheduled basis
(weekly) using run-parts.
run-parts ignores any files that are hidden or dotfiles (.*) or backup
files (*~ or *,) or named *.{rpmsave,rpmorig,rpmnew,swp,cfsaved} and handles
the files named jobs.deny and jobs.allow specially.
In this specific example, the chronograph script is the only script or job file
executed on a weekly basis (due to white-listing it in jobs.allow). And the
README and chrono.dat file are ignored either as a result of being black-listed
in jobs.deny or because they are NOT white-listed in the jobs.allow file.
For more details, please see ../README.cron file.

View File

@ -1 +0,0 @@
Time And Relative D...n In Execution (Open)Shift!

View File

@ -1,3 +0,0 @@
#!/bin/bash
echo "`date`: `cat $(dirname \"$0\")/chrono.dat`"

View File

@ -1,12 +0,0 @@
#
# Script or job files listed in here (one entry per line) will be
# executed on a weekly-basis.
#
# Example: The chronograph script will be executed weekly but the README
# and chrono.dat files in this directory will be ignored.
#
# The README file is actually ignored due to the entry in the
# jobs.deny which is checked before jobs.allow (this file).
#
chronograph

View File

@ -1,7 +0,0 @@
#
# Any script or job files listed in here (one entry per line) will NOT be
# executed (read as ignored by run-parts).
#
README

View File

@ -1 +0,0 @@
web: node init.js

741
deps/discrete.js vendored
View File

@ -1,741 +0,0 @@
module.exports=require('theory')((function(){
var discrete = {};
discrete.name = 'discrete';
discrete.author = 'Mark';
discrete.version = 1.2;
root.opts.discrete = root.opts.discrete||{};
discrete.dep = [];
window.jQuery? '': root.opts.discrete.jquery?
discrete.dep.push(root.opts.discrete.jquery) : console.log('Error: Needs jQuery! Include it or assign a path to `root.opts.discrete.jquery`');
discrete.init = (function(a){
console.log('discrete.init');
function the(){ return the };
the.os = (function(){
function os(){ return os };
var ua = navigator.userAgent, lua = a.text.low(ua);
os.is = (function(){
function is(q){
return (q)?(is.win||is.lin||is.mac||is.and||is.ios||"unknown"):is;
} if(root.page){
is.win = (ua.search("Win") >= 0)? "Windows":false;
is.lin = (ua.search("Linux") >= 0)? "Linux":false;
is.mac = (ua.search("Mac") >= 0)? "Macintosh":false
is.and = (lua.search("android") >= 0)? "Android":false
is.ios = (lua.search('ipod') >= 0
|| lua.search('iphone') >= 0
|| lua.search('ipad') >= 0)? "iOS":false
} else {
is.node = true;
} return is;
})();
os.wkv = a.num.dec(a.list(ua.match(/AppleWebKit\/([\d\.]+)/)).at(-1));
if(os.is.and){
var s = '', v = a.list(ua.match(/Android\s+([\d\.]+)/)).at(-1);
a.list(a.num(v).ify([])).each(function(v,i){
s += (v*100+'').slice(0,3);
});
os.version = os.V = a.num.ify(s);
} return os;
})();
the.device = (function(){
function device(){ return device };
device.is = (function(){
function is(){ return is };
is.touch = (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch); // via Modernizer
is.oriented = ('onorientationchange' in window) || ('orientation' in window);
return is;
})();
device.size = (function(){
function size(){ return size };
size.x = size.width = screen.width;
size.y = size.height = screen.height;
return size;
})();
device.rotate = (function(fn){
if(a.fns.is(fn)){
return a.on('discrete-rotate').event(fn);
}
device.vertical = ($(window).height() > $(document).width())? true : false;
device.horizontal = !device.vertical;
a.on('discrete-rotate').emit();
});
return device;
})();
the.event = (function(){ // TODO: MARK: RE-EXAMINE NOW THAT THEORY SUPPORTS EVENTS.
var event = {}, events = [];
event.arg = (function(args,w,h){
var m = {way:w,how:h};
var jq = a.list(args.o).at(1);
if(jq){
m.where = jq.jquery? jq : $(jq);
m.what = a.text.caps(a.list(args.t).at(1));
}else{
if(args.t.length == 2){
m.what = a.text.caps(a.list(args.t).at(1));
m.where = $(a.list(args.t).at(2));
}else{
m.where = $(a.list(args.t).at(1));
}
}
m.cb = a.list(args.f).at(1);
events.push(m);
return m;
});
event.emit = (function(e){
//console.log("--");
a.list(events).each(function(v,i){
if(v.way && e.way != v.way){
return;
}
if(v.how && e.how != v.how){
return;
}
if(v.what && a.text.caps(e.what) != v.what){
return;
}
//console.log(e.way +" == "+ v.way +" :: "+ e.how +" == "+ v.how +" :: "+ e.what +" == "+ v.what);
if(
v.where[0] == window || v.where.is(document) ||
$(e.where).closest(v.where.selector||v.where).length
){
v.cb(e);
}
});
});
return event;
})();
the.mouse = (function(){
function mouse(){ return mouse; }
mouse.x = 0;
mouse.y = 0;
mouse.left = false;
mouse.right = false;
mouse.move = (function(e){
var m = the.event.arg(a.fns.sort(a.list.slit.call(arguments, 0)),mouse.name,'move');
});
mouse.down = (function(e){
var m = the.event.arg(a.fns.sort(a.list.slit.call(arguments, 0)),mouse.name,'down');
});
mouse.up = (function(h,fn,e){
var m = the.event.arg(a.fns.sort(a.list.slit.call(arguments, 0)),mouse.name,'up');
});
mouse.click = (function(e){
var m = the.event.arg(a.fns.sort(a.list.slit.call(arguments, 0)),mouse.name,'click');
});
mouse.dbl = (function(e){
var m = the.event.arg(a.fns.sort(a.list.slit.call(arguments, 0)),mouse.name,'dbl');
});
mouse.point = (function(s,h,v){ // WARNING! This uses some potentially dangerous tricks which might not work for your page.
var stack = [], d = [], c = 0, e, e_, b = $('body'), scroll = b.scrollTop(), x = true;
if(document.elementFromPoint){
while(x
&& (e=the.mouse.at(h||the.mouse.horizontal,v||the.mouse.vertical))
&& e.style && e.nodeName != 'HTML'
){
if(s && $ && $(e).is(s)){
x = false;
} if(e == e_){
e.style.display = 'none';
} else {
w = e.style.cssText;
e.style.width = e.style.maxWidth = e.style.minWidth =
e.style.paddingLeft = e.style.paddingRight =
e.style.marginLeft = e.style.marginRight =
e.style.mouseStacker = 0;
stack.push(e_=e);
d.push(w)
}
}
} else if(window.event) {
stack.push(window.event.target);
}
a.list(stack).each(function(e,i){
e.style.cssText = d[--i];
});
b.scrollTop(scroll);
return stack;
});
mouse.poke = (function(e,t,c){
if(!e.time && !t){ return 0 }
if(e.time && e.time.scroll != $(document).scrollTop()){ return 0 } // TODO: BUG: Potential? HACK: if scroll pos changed since down, then no go.
c = c || [];
c[0] = c[0] || c[0] === 0? c[0] : the.mouse._x;
c[1] = c[1] || c[1] === 0? c[1] : the.mouse._y;
if(a.time.is() - (t||e.time.up) < the.touch.opt.dbl && (
Math.abs(the.mouse.x - c[0]) <= the.touch.opt.radius
&& Math.abs(the.mouse.y - c[1]) <= the.touch.opt.radius
)){ return 2 }
if(a.time.is() - (t||e.time.down) < the.touch.opt.click && (
Math.abs(the.mouse.x - c[0]) <= the.touch.opt.radius
&& Math.abs(the.mouse.y - c[1]) <= the.touch.opt.radius
)){ return 1 }
return 0;
});
mouse.hold = (function(e,r){
if(!e.time){ return 0 }
if(e.time.scroll != $(document).scrollTop()){ return 0 } // TODO: BUG: Potential? HACK: if scroll pos changed since down, then no go.
if(Math.abs(the.mouse.x - the.mouse._x) <= (r||the.touch.opt.radius)
&& Math.abs(the.mouse.y - the.mouse._y) <= (r||the.touch.opt.radius)
){
return a.time.is() - e.time.down;
} return 0;
});
mouse.which = (function(e){
if(e.way != 'mouse'){ return 'left' }
function left(e){
if (e.which) {
if(e.which == 3) return false;
else if(e.which == 1) return true;
} else if (e.button) {
if(e.button == 2) return false;
else if(e.button == 1) return true;
}
}
function right(e){
return !left(e);
}
if(left(e)) {
mouse.left = true;
return "left";
} else if(right(e)) {
mouse.right = true;
return "right";
}
});
mouse.on = (function(){
var on = {};
on.time = {down:0,up:0};
on.down = (function(e){
if(!e) return false;
e.way = mouse.name;
e.how = 'down';
e.where = e.target;
e.what = mouse.which(e);
e[e.what] = true;
mouse._x = mouse.x;
mouse._y = mouse.y;
mouse.horizontal = e.clientX;
mouse.vertical = e.clientY;
on.time.down = a.time.is();
on.time.scroll = $(document).scrollTop();
the.event.emit(e);
return true; // DETERMINE EXCEPTIONS
});
on.up = (function(e){
if(!e) return false;
e.way = mouse.name;
e.where = e.target;
e.what = mouse.which(e);
e[e.what] = true;
on.poke(e,on.time);
e.how = 'up';
e.time = on.time;
the.event.emit(e,on.time);
on.time.up = a.time.is();
mouse[e.what] = false;
return true;
});
on.move = (function(e){
if(!e) return false;
e.way = mouse.name;
e.how = 'move';
e.where = e.target;
mouse.x_ = mouse.x;
mouse.y_ = mouse.y;
mouse.horizontal = e.clientX;
mouse.vertical = e.clientY;
if(e.pageX || e.pageY){
mouse.x = e.pageX;
mouse.y = e.pageY;
mouse.target = e.target;
} else if(e.clientX || e.clientY){
mouse.x = e.clientX + document.body.scrollLeft
+ document.documentElement.scrollLeft;
mouse.y = e.clientY + document.body.scrollTop
+ document.documentElement.scrollTop;
mouse.target = e.srcElement;
}
the.event.emit(e);
});
on.poke = (function(e,t){ return });
on.click = (function(e,p){
if(!e) return false;
e.how = 'click';
e.where = e.where||e.target;
e.what = mouse.which(e);
e[e.what] = true;
e.way = p? mouse.name : e.way||mouse.name;
the.event.emit(e);
mouse[e.what] = false;
return true;
});
on.dbl = (function(e){
if(!e) return false;
e.way = e.way||mouse.name;
e.how = 'dbl';
e.where = e.where||e.target;
e.what = mouse.which(e);
e[e.what] = true;
the.event.emit(e);
mouse[e.what] = false;
return true;
});
return on;
})();
return mouse;
})();
the.key = (function(){
function key($){
key.$ = $ !== undefined? $ : undefined;
return key;
}
key.e = window.event;
key.is = '';
key._is = '';
key.combo = [];
key.trail = [];
key.opt = {forget:1000};
key.down = (function(h,fn,e){
var m = key.on.arg(key.$, a.fns.sort(a.list.slit.call(arguments, 0)));
m.down = m.cb;
key.on.arch(m,key.on.down_,'-'); // this makes '-' unusuable if we're splitting on it, need to add option for this and handle runs, combos, etc.
});
key.hold = (function(h,fn,e){
var m = key.on.arg(key.$, a.fns.sort(a.list.slit.call(arguments, 0)));
m.hold = m.cb;
key.on.arch(m,key.on.hold_,'-'); // same as above
});
key.up = (function(h,fn,e){
var m = key.on.arg(key.$, a.fns.sort(a.list.slit.call(arguments, 0)));
m.up = m.cb;
key.on.arch(m,key.on.up_,'-'); // same as above
});
key.on = (function(m){
var on = {}, level = [], arch;
on.arg = (function(k, args){
var m = {};
m.key = k || a.text.caps(a.list(args.t).at(1));
m.key = (m.key === '')? 'all' : m.key;
m.cb = a.list(args.f).at(1);
var jq = a.text.caps(a.list(args.o).at(1));
if(jq){
m.jq = jq.jquery? jq : $(jq);
}else{
jq = a.text.caps(a.list(args.t).at(2));
jq = (jq === 'DOCUMENT')? window.document : (jq === 'WINDOW')? window : '';
m.jq = $(jq);
}
return m;
});
on.down = (function(e){
if(!e) return false;
e.way = key.name;
e.where = e.target;
e.code = e.keyCode;
e.tag = e.key = key._is = a.text.caps(key.tag(e));
key.e = e;
e.how = 'hold';
key.on.emit(e,key.on.hold_);
if(key.on[key._is]) return a("key.tame->")();
key.e.how = e.how = 'down';
key.on[key.is = key._is] = true;
key.on.emit(e,key.on.down_);
key.combo.push(key.is);
key.trail.push(key.is);
key.trail = key.trail.slice(-12);
return a(the,"key.tame->")(e);
});
on.up = (function(e){
if(!e) return false;
e.way = key.name;
e.how = 'up';
e.where = e.target;
e.code = e.keyCode;
e.tag = e.key = key.is_ = a.text.caps(key.tag(e));
key.e = e;
key.on[key.is_] = false;
key.combo = a.list(key.combo).each(function(v,i,t){
if(v === key.is_){ return }
t(v);
})||[];
key.on.emit(e,key.on.up_);
key.is = '';
return true; // DETERMINE EXCEPTIONS
});
on.arch = (function(m,w,s){
var arch = w, al;
m.key = a.text.caps(m.key);
al = m.key.split(s);
a.list(al).each(function(u,h){
if(!a.obj.get(arch,u)){
if(al.length == h){
arch[u] = {map:m};
}else{
arch[u] = {};
}
}
arch = arch[u];
});
});
on.emit = (function(e,w){
var r;
a(w,'ALL.map.'+e.how+'->')(e);
arch = a.list(level).at(-1)||w;
if(r = arch[e.tag]){
a.time.stop(on.forget);
a(r,'map.'+e.how+'->')(e);
if(a.obj(r).each(function(v,i){
if(a.obj.is(v) && i != 'map') return true;
})){
level.push(r);
}
on.forget = a.time.wait(function(){
level = [];
},key.opt.forget);
return;
}
});
on.forget;
on.down_ = {};
on.hold_ = {};
on.up_ = {};
return on;
})();
key.tag = (function(code){
if(!code) return false;
code = (code.keyCode)?code.keyCode:code;
code = (typeof code == 'number')? 'kc'+code:code;
return key.special[code] || String.fromCharCode(a.num.ify(code.substring(2)));
});
key.code = (function(tag){
if(!tag) return false;
return (key.special[tag.toLowerCase()])? key.special[tag.toLowerCase()] : a.text.caps(tag).charCodeAt(0);
});
key.tame = function(){return !(key._is in key.strange)};
key.strange = {' ':1,ERASE:1};
key.reserved = {Z:1,X:1,C:1,V:1,R:1,T:1,N:1,F12:1,F11:1,PU:1,PD:1,pu:1,pd:1}; // reserved keys
key.special = {
'esc':27
,'kc27': 'esc'
,'tab':9
,'kc9':'tab'
,' ':32
,'kc32':' '
,'enter':13
,'kc13':'enter'
,'erase':8
,'kc8': 'erase'
,'kc92':'\\'
,'\\':92
,'scroll':145
,'kc145':'scroll'
,'caps':20
,'kc20':'caps'
,'num':144
,'kc144':'num'
,'pause':19
,'kc19':'pause'
,'insert':45
,'kc45':'insert'
,'home':36
,'kc36':'home'
,'delete':46
,'kc46':'del'
,'end':35
,'kc35':'end'
,'pu':33
,'kc33':'pu'
,'pd':34
,'kc34':'pd'
,'left':37
,'kc37':'left'
,'up':38
,'kc38':'up'
,'right':39
,'kc39':'right'
,'down':40
,'kc40':'down'
,'shift':16
,'kc16':'shift'
,'ctrl':17
,'kc17':'ctrl'
,'alt':18
,'kc18':'alt'
,'¤':91
,'cmd':91
,'kc91':((the.os.is.win||the.os.is.lin||the.os.is.and)?'¤':'cmd')
,'kc91':'['
,'[':91
,'kc93':']'
,']':93
,'kc126':'`'
,'`':126
,'kc95':'-'
,'-':95
,'kc61':'='
,'=':61
,'kc59':';'
,';':59
,'kc222':"'"
,"'":222
,'kc47':'/'
,'/':47
,'kc62':'.'
,'.':62
,'kc44':','
,',':44
,'f1':112
,'kc112':'F1'
,'f2':113
,'kc113':'F2'
,'f3':114
,'kc114':'F3'
,'f4':115
,'kc115':'F4'
,'f5':116
,'kc116':'F5'
,'f6':117
,'kc117':'F6'
,'f7':118
,'kc118':'F7'
,'f8':119
,'kc119':'F8'
,'f9':120
,'kc120':'F9'
,'f10':121
,'kc121':'F10'
,'f11':122
,'kc122':'F11'
,'f12':123
,'kc123':'F12'
};
return key;
})();
the.touch = (function(){
var touch = {};
a.log(touch.name = 'touch');
touch.opt = {
click: 250
,dbl: 500
,radius: 50
,mouse: true
,react: true
}
touch.count = 0;
touch.point = [{},{},{},{},{},{},{},{},{},{},{}];
touch.move = (function(e){
var m = the.event.arg(a.fns.sort(a.list.slit.call(arguments, 0)),touch.name,'move');
});
touch.down = (function(e){
var m = the.event.arg(a.fns.sort(a.list.slit.call(arguments, 0)),touch.name,'down');
});
touch.up = (function(e){
var m = the.event.arg(a.fns.sort(a.list.slit.call(arguments, 0)),touch.name,'up');
});
touch.gest = (function(b,c,fn){
var gest = {};
a.log(gest.name = 'gest');
gest.angle = 0;
gest.scale = 1.0;
gest.start = (function(e){
});
gest.morph = (function(e){
gest.angle = e.rotation;
gest.scale = e.scale;
$(document).trigger('touch/gest/morph');
});
gest.end = (function(e){
});
return gest;
})();
touch.time = {down:0,up:0};
touch.on = (function(){
var on = {};
on.down = (function(e){
the.mouse.target = false;
var multi = e.touches || [{}], on = e.changedTouches;
the.mouse._x = the.mouse.x_ = the.mouse.x = multi[0].pageX;
the.mouse._y = the.mouse.y_ = the.mouse.y = multi[0].pageY;
the.mouse.horizontal = multi[0].clientX;
the.mouse.vertical = multi[0].clientY;
touch.count = multi.length;
a.list(multi).each(function(v,i){
v._x = v.x_ = v.x = v.pageX;
v._y = v.y_ = v.y = v.pageY;
touch.point[v.id = i] = v||{};
});
e.way = touch.name;
e.what = touch.count;
e.where = multi[0].target;
e.stun = jQuery.Event.stun;
e.stop = jQuery.Event.stop;
e.how = 'down';
touch.time.down = a.time.is();
touch.time.scroll = $(document).scrollTop();
the.event.emit(e);
});
on.move = (function(e){
var multi = e.touches || [{}];
the.mouse.x = the.mouse.x_ = multi[0].pageX;
the.mouse.y = the.mouse.y_ = multi[0].pageY;
the.mouse.horizontal = multi[0].clientX;
the.mouse.vertical = multi[0].clientY;
a.list(multi).each(function(v,i){
v.x = v.x_ = v.pageX;
v.y = v.y_ = v.pageY;
if(!v.id) touch.point[v.id = i] = v||{}; // Android does not update without this.
});
e.way = touch.name;
e.how = 'move';
e.where = multi[0].target;
e.what = touch.count;
e.stun = jQuery.Event.stun;
e.stop = jQuery.Event.stop;
the.event.emit(e);
});
on.up = (function(e){
var t = a.time.is(), multi = e.changedTouches;
e.what = touch.count;
if((touch.count = multi.length) == 0){
touch.point = [{},{},{},{},{},{},{},{},{},{},{}];
}
e.way = touch.name;
e.where = multi[0].target;
e.stun = jQuery.Event.stun;
e.stop = jQuery.Event.stop;
if(touch.count === 1){ the.mouse.on.poke(e,touch.time) }
e.how = 'up';
e.time = touch.time;
the.event.emit(e);
touch.time.up = a.time.is();
});
return on;
})();
touch.feel = (function(e){
touch.opt.react = e = a.bi.is(e)?e:!touch.opt.react;
if(e){
try{
document.addEventListener("touchmove", touch.on.move, true);
document.addEventListener('touchstart', touch.on.down, true);
document.addEventListener('touchend', touch.on.up, true);
document.addEventListener("gesturechange", touch.gest.morph, true);
document.addEventListener('gesturestart', touch.gest.start, true);
document.addEventListener('gestureend', touch.gest.end, true);
}catch(e){
}
} else {
console.log('touchless ?');
try{
document.removeEventListener("touchmove", touch.on.move, true);
document.removeEventListener('touchstart', touch.on.down, true);
document.removeEventListener('touchend', touch.on.up, true);
document.removeEventListener("gesturechange", touch.gest.morph, true);
document.removeEventListener('gesturestart', touch.gest.start, true);
document.removeEventListener('gestureend', touch.gest.end, true);
}catch(e){
}
}
});
return touch;
})();
the.drag = (function(){
var drag = {};
a.log(drag.name = 'drag');
drag.enter = (function(e){
$(document).trigger('dragenter',[e]);
});
drag.over = (function(e){
$(document).trigger('dragover',[e]);
});
drag.drop = (function(e){
$(document).trigger('mousemove',[e]);
$(document).trigger('dragdrop',[e]);
e.preventDefault();
return false;
});
drag.change = (function(e){
$(document).trigger('dragchange',[e]);
});
return drag;
})();
the.doc = doc = {}
/** -------- INITIATE JQUERY BINDINGS -------- **/
if(root.page){
$(document).ready(function(){
jQuery.Event.stun = (function(e){(e||this).preventDefault();return (e||this)});
jQuery.Event.stop = (function(e){(e||this).stopPropagation();return (e||this)});
jQuery.Event.prototype.stun = jQuery.Event.stun;
jQuery.Event.prototype.stop = jQuery.Event.stop;
$(document).scroll(function(e){
//the.touch.scroll = a.time.is(); iOS calls scroll after touch/mouse events.
}).mousemove(function(e,el){
if(el) e = el;
if(!e) var e = window.event;
e.stopPropagation();e.preventDefault();
the.mouse.on.move(e);
}).mousedown(function(e){
if(!e) var e = window.event;
if(the.mouse.on.down(e)){
return true;
}
e.stopPropagation();e.preventDefault();
}).mouseup(function(e){
if(!e) var e = window.event;
if(the.mouse.on.up(e)){
return true;
}
e.stopPropagation();e.preventDefault();
}).click(function(e){ // iOS only emits on clickable elements
the.mouse.on.click(e);
}).dblclick(function(e){
the.mouse.on.dbl(e);
}).keydown(function(e){
if(the.key.on.down(e)){ return true }
}).keyup(function(e){
if(the.key.on.up(e)){ return true }
});
/** -- DEFAULT SETTINGS -- **/
$(document).on('focus',"textarea, input, [contenteditable=true]",function(){
the.key.combo = []; // iOS not trigger 'keyup' sometimes on input exits, so clear combo manually.
the.key.tame = function(){return true};
}).on('blur',"textarea, input, [contenteditable=true]",function(){
the.key.combo = []; // iOS not trigger 'keyup' sometimes on input exits, so clear combo manually.
the.key.tame = function(){return false}; // PREVENT UNLOAD & SCROLL BOTTOM
});
(document.body||{}).onorientationchange = the.device.rotate;
});
(function(window){
the.touch.feel(the.touch.opt.react);
try{
document.addEventListener('dragenter', the.drag.enter, false);
document.addEventListener("change", the.drag.change, false);
document.addEventListener('drop', the.drag.drop, false);
document.addEventListener('dragover', the.drag.over, false);
}catch(e){console.log("drag fail", e);};
function afocus(e){
if(e) if(e.target != window) return true;
the.key.combo = [];
};
document.onfocusin = afocus;
window.onfocus = afocus;
})(window);
}
return the;
});
return discrete;
})());

2
deps/jquery.js vendored

File diff suppressed because one or more lines are too long

30
deps/key/LTIE9.css vendored
View File

@ -1,30 +0,0 @@
/* IE6 POSITON: FIXED; FLICKER: NONE; */
*html body,*html html{background-image:url(about:blank);background-attachment:fixed;}
*html #keys-top{
position: absolute;
top:expression(eval(document.compatMode&&document.compatMode=='CSS1Compat')?
documentElement.scrollTop+((0))
:document.body.scrollTop+((0)));
}
*html #keys-main{
position: absolute;
top:expression(eval(document.compatMode&&document.compatMode=='CSS1Compat')?
documentElement.scrollTop+((documentElement.clientHeight-this.clientHeight))
:document.body.scrollTop+((document.body.clientHeight-this.clientHeight)));
}
*html #keyboard {
position: fixed;
padding: 0;
margin: 0;
width: auto;
height: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.keyboard li {
background: black;
background: white;
}

151
deps/key/key.css vendored
View File

@ -1,151 +0,0 @@
#keyface{
z-index: 99999999;
}
#keyput {
display: none;
text-align: center;
width: 240px;
margin-left: -120px;
padding: .5em 0;
border: none;
z-index: 9999;
background-color: rgba(100%,100%,100%,.65);
border-radius: 7px;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
-moz-box-shadow: #6FA1D9 0px 0px 10px -2px inset;
-webkit-box-shadow: #6FA1D9 0px 0px 10px -2px inset;
box-shadow: #6FA1D9 0px 0px 10px -2px inset;
}#keyput:focus {
outline: none;
}
#keyboard, .keyboard {
position: fixed;
height: 100%;
width: 0px;
bottom: 0px;
left: 50%;
right: 50%;
z-index: 99999999;
font-family: 'Trebuchet MS', sans-serif;
text-rendering: optimizeLegibility;
}
.key-a {
cursor: pointer;
}
.punc {
display: none;
}
.key-offset {
visibility: hidden;
}
.keyboard ul {
position:relative;
list-style-type: none;
clear: both;
margin: 0;
padding: 0;
d-isplay: none;
}
.keyboard li, .keyboard .key {
display: none;
float:left;
min-width: 2em;
padding: .4em .4em;
margin: .2em;
text-align: center;
text-shadow: none;
border-radius: 7px;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
-moz-box-shadow: #6FA1D9 0px 0px 10px -2px;
-webkit-box-shadow: #6FA1D9 0px 0px 10px -2px;
box-shadow: #6FA1D9 0px 0px 10px -2px;
color: white;
background-color: rgba(0,0,0,.75);
color: #999;
background-color: rgba(100%,100%,100%,.65);
}
#keys-top {
position: fixed;
top: 0;
overflow: visible;
b-ackground: rgba(0,0,0,.5);
}
#keys-main {
position: fixed;
width: 100%;
padding: 0;
right: 0;
bottom: 0;
left: 0;
overflow: visible;
b-ackground: rgba(0,0,0,.5);
max-height: 150px; /* Bug? Prevent Jumpyness */
}
#keys-left {
position: absolute;
left: 0;
bottom: 0;
z-index: 0;
b-ackground: green;
}
#keys {
text-align: center;
z-index: 1;
b-ackground: blue;
}
#keys-right {
position: absolute;
right: 0;
bottom: 0;
z-index: 0;
b-ackground: red;
}
.key-rowR {
float: right;
}
.key-bumpL {
margin-left: -35px;
}
.key-mtextc {
margin: 0px;
text-align: center;
}
#instr {
text-align: center;
font-family: 'Trebuchet MS', sans-serif;
text-rendering: optimizeLegibility;
text-shadow: 10px 10px 25px rgba(100%,100%,100%,.9)
,-5px -5px 25px rgba(100%,100%,100%,.9)
,-5px 10px 25px rgba(100%,100%,100%,.9)
,10px -5px 25px rgba(100%,100%,100%,.9);
box-shadow: none;
color: white;
color: black;
background: rgba(0,0,0,.25);
background: transparent;
font-size: 12pt;
padding: 2px 0px;
}
.hide {
display: none;
}
.show {
display: block;
}

131
deps/key/key.html vendored
View File

@ -1,131 +0,0 @@
<!DOCTYPE html>
<html>
<body>
<div id="keyboard" class="keyboard" style="display: none;">
<!--[if lt IE 9]>
<link rel="stylesheet" href="/+/key/LTIE9.css">
<![endif]-->
<div id="keys-top">
<ul id="kt1">
<li id="kc27" class="alphanum lhand">esc</li>
<li id="kc112" class="alphanum lhand">F1</li>
<li id="kc113" class="alphanum lhand">F2</li>
<li id="kc114" class="alphanum lhand">F3</li>
<li id="kc115" class="alphanum lhand">F4</li>
<li id="kc116" class="alphanum lhand">F5</li>
<li id="kc117" class="alphanum lhand">F6</li>
<li id="kc118" class="alphanum rhand">F7</li>
<li id="kc119" class="alphanum rhand">F8</li>
<li id="kc120" class="alphanum rhand">F9</li>
<li id="kc121" class="alphanum rhand">F10</li>
<li id="kc122" class="alphanum rhand">F11</li>
<li id="kc123" class="alphanum rhand">F12</li>
</ul>
<ul id="kt2" class="key-bumpL">
<li style="min-width: 1.9em;" id="kc126">`</li>
<li id="kc49" class="alphanum lhand">1</li>
<li id="kc50" class="alphanum lhand">2</li>
<li id="kc51" class="alphanum lhand">3</li>
<li id="kc52" class="alphanum lhand">4</li>
<li id="kc53" class="alphanum lhand">5</li>
<li id="kc54" class="alphanum lhand">6</li>
<li id="kc55" class="alphanum rhand">7</li>
<li id="kc56" class="alphanum rhand">8</li>
<li id="kc57" class="alphanum rhand">9</li>
<li id="kc48" class="alphanum rhand">0</li>
<li id="kc95" class="alphanum rhand">-</li>
<li id="kc61" class="alphanum rhand">=</li>
<li class="mod" style="text-align: right; min-width: 3.5em;" id="kc8">erase</li>
</ul>
</div>
<div id="keys-main">
<div id="keys-left">
<ul id="kl1">
<li class="mod" style="text-align: left; min-width: 3.2em;" id="kc9">tab</li>
</ul>
<ul id="kl2">
<li class="mod" style="text-align: left; min-width: 3.75em;" id="kc20">caps</li>
</ul>
<ul id="kl3">
<li class="mod" style="text-align: left; min-width: 5.3em;" id="kc16">shift</li>
</ul>
<ul id="kl4">
<li class="mod" style="text-align: left; min-width:50px" id="kc17">ctrl</li>
<li class="mod" style="min-width: 3.2em;" id="kc91">&curren;</li>
<li class="mod" style="min-width: 3.2em;" id="kc18">alt</li>
</ul>
</div>
<div id="instr" class="key-mtextc">
<span class="instr"></span>
</div>
<div id="keys">
<ul id="kp1">
<li id="kc81" class="alphanum lhand">Q</li>
<li id="kc87" class="alphanum lhand">W</li>
<li id="kc69" class="alphanum lhand">E</li>
<li id="kc82" class="alphanum lhand">R</li>
<li id="kc84" class="alphanum lhand">T</li>
<li id="kc89" class="alphanum rhand">Y</li>
<li id="kc85" class="alphanum rhand">U</li>
<li id="kc73" class="alphanum rhand">I</li>
<li id="kc79" class="alphanum rhand">O</li>
<li id="kc80" class="alphanum rhand">P</li>
<li id="kc91" class="alphanum rhand punc">[</li>
<li id="kc93" class="alphanum rhand punc">]</li>
<li id="kc92" class="alphanum rhand punc">\</li>
</ul>
<ul id="kp2">
<li class="key-offset" style="min-width:8px;padding:1px;margin:0px;"></li>
<li id="kc65" class="alphanum lhand">A</li>
<li id="kc83" class="alphanum lhand">S</li>
<li id="kc68" class="alphanum lhand">D</li>
<li id="kc70" class="alphanum lhand">F</li>
<li id="kc71" class="alphanum lhand">G</li>
<li id="kc72" class="alphanum rhand">H</li>
<li id="kc74" class="alphanum rhand">J</li>
<li id="kc75" class="alphanum rhand">K</li>
<li id="kc76" class="alphanum rhand">L</li>
<li id="kc59" class="alphanum rhand punc">;</li>
<li id="kc222" class="alphanum rhand punc">'</li>
</ul>
<ul id="kp3">
<li class="key-offset" style="min-width:33px;padding:1px;margin:0px;"></li>
<li id="kc90" class="alphanum lhand">Z</li>
<li id="kc88" class="alphanum lhand">X</li>
<li id="kc67" class="alphanum lhand">C</li>
<li id="kc86" class="alphanum lhand">V</li>
<li id="kc66" class="alphanum lhand">B</li>
<li id="kc78" class="alphanum rhand">N</li>
<li id="kc77" class="alphanum rhand">M</li>
<li id="kc44" class="alphanum rhand punc">,</li>
<li id="kc62" class="alphanum rhand punc">.</li>
<li id="kc47" class="alphanum rhand punc">/</li>
</ul>
<input id="keyput"/>
</div>
<div id="keys-right">
<ul id="kr1" class="key-rowR">
<li class="mod rhand" style="text-align: right; min-width: 4.5em;" id="kc13">enter</li>
</ul>
<ul id="kr2" class="key-rowR">
<li class="mod rhand" style="text-align: right; min-width: 5.9em; float: none;" id="kc16">shift</li>
<li id="kc38" class="arrow">&uarr;</li>
<!--
-->
</ul>
<ul id="kr3" class="key-rowR">
<li class="mod" style="min-width: 3.2em;" id="kc18">alt</li>
<li class="mod" style="min-width: 3.2em;" id="kc91">&curren;</li>
<li class="mod" style="min-width: 3.2em;" id="kc17">ctrl</li>
<li id="kc37" class="arrow">&larr;</li>
<li id="kc40" class="arrow">&darr;</li>
<li id="kc39" class="arrow">&rarr;</li>
<!--
-->
</ul>
</div>
</div>
</div>
</body>
</html>

185
deps/key/key.js vendored
View File

@ -1,185 +0,0 @@
module.exports=require('theory')((function(){
var key = {};
key.name = 'key';
key.author = 'Mark';
key.version = 4;
root.opts.kiwi = root.opts.kiwi||{};
key.deps = ['../discrete'];
key.init = (function(a){
var the = a.discrete || theory.discrete;
$(document).ready(function(){
root.opts.key = root.opts.key || {};
var kf = $("#keyface"), h = root.opts.key.host||'';
if(!kf.length){
$("body").append("<div id='keyface'></div>");
$('head').append('<link rel="stylesheet" href="'+h+'/key/key.css">');
kf = $('#keyface').load(h+"/key/key.html",function(){
r.init();
});
} else {
r.init();
}
});
var doc = {
skin: {
a: {color:'#000'}
,on: {}
,dull: {color:'#999'}
,scale: {
touch: {'font-size':'1.25em'}
,key: {'font-size':'1em'}
}
,slide: {
up: 175
,down: 200
}
}
}, realboard = (function(){ return !the.device.is.oriented })
layout = (function(doc){
var lo = {};
lo.doc = doc||{};
lo.size = {};
lo.kb = $("#keyboard");
lo.kt = $("#keys-top");
lo.km = $("#keys-main");
lo.kl = $("#keys-left");
lo.kr = $("#keys-right");
lo.k = $("#keys");
lo.widths = (function(){
var r = {};
r.lx = lo.width(lo.kl,{max:true,out:true})||0;
r.kx = lo.width(lo.k,{max:true,out:true})||0;
r.rx = lo.width(lo.kr,{max:true,out:true})||0;
r.tx = lo.width(lo.kt,{max:true,out:true})||0;
return r;
});
lo.set = function(e,c){
lo.size.x = $(document).width();
lo.size.o = lo.size.x/2;
lo.size.max = lo.widths();
lo.k.css({ width: lo.size.max.kx, 'margin-left': 'auto', 'margin-right':'auto' });
lo.kt.css({ width: lo.size.max.tx, left: lo.size.o - lo.size.max.tx/2 });
//console.log(lo.size.max.kx);
var bk = lo.k.find("ul.key-row-a").last().find("li:visible").not(".key-offset")
,bkflp = (bk.first().position()||{left:0}).left
,bkfl = (lo.k.offset()||{left:0}).left + bkflp;
//console.log(bkfl +" < "+ lo.size.max.lx);
if(bkfl < lo.size.max.lx){
if(!c && realboard()){
if(lo.size.x <= (lo.size.max.lx - bkflp) + lo.size.max.kx || lo.size.x <= lo.size.max.tx
|| lo.size.x - lo.size.max.rx <= ((bk.last().offset()||{left:0}).left + bk.last().outerWidth(true))
){
lo.kb.find("li:not(.key-a)").hide();
return lo.set(e,true);
}
}
lo.k.css({'margin-left': lo.size.max.lx - bkflp });
}
};
lo.width = function(a,b){
var x = 1, aa = a.children("ul.key-row-a").first(), b = b||{};
b.out = b.out||false;
b.max = b.max||false;
b.filter = b.filter||':visible';
a.children("ul.key-row-a").each(function(){
aa = (aa.children('li'+b.filter).length < $(this).children('li'+b.filter).length)?
((b.max)? $(this) : aa) : ((b.max)? aa : $(this));
});
aa.children('li'+b.filter).each(function(){
x += Math.ceil($(this).outerWidth(b.out)||1);
});
return ++x;
}
lo.track = function(i){
lo.set();
lo.doc.initset = true;
$(window).resize(lo.set);
}
return lo;
}),
r = (function(m){
var k = {};
k.map = (function(o){
var tag, code, s, j, x = 1, d, row, rowi, ul = {}, punc = {}, uls = {}
,npunc = ":not(.punc)", w = $(document).width();
k.go = true;
k.wipe(function(){
k.go = false;
a.obj(o).each(function(v,i){
if(!v || v.key || i === 'tag'){ return }
tag = a.text.caps(i);
code = the.key.code(tag);
tag = $.isFunction(v.tag)? v.tag() : (v.tag||v||undefined);
j = $("#kc"+code).show().addClass('key-a').css(doc.skin.a).html(tag);
//console.log(" - "+j.outerWidth(true));
row = j.closest('ul').addClass('key-row-a');
d = d || row;
rowi = row.attr('id');
ul[rowi] = row;
if(j.is('.punc')){
npunc = "";
}
});
if(realboard()){
//x = layout.width(,{out:true,filter: npunc});
a.obj(ul).each(function(v,i){
d = (d.children('li'+npunc).length < v.children('li'+npunc).length)?
v : d;
});
(d||$()).children("li"+npunc).each(function(){ // + npunc possibly wrong! actually most def is.
x += Math.ceil($(this).outerWidth(true)||1);
});
}
a.obj(ul).each(function(v,i){
if(realboard() && x < w){
v.children('li'+npunc).show();
}
v.slideDown(doc.skin.slide.down);
});
k.layout();
});
return true;
});
k.wipe = (function(fn){
if(!k || !k.b){ return }
if(!k.on){ k.on = k.b.show() }
k.$put.blur().hide().val('');
var c = 0, l;
l = k.$rows.stop(true,true).removeClass('key-row-a').removeAttr('style').length;
k.$rows.slideUp(doc.skin.slide.up,function(){
$(this).empty().append(k.row[$(this).attr('id')].clone());
}).promise().done(fn);
});
k.instr = (function(s){
if(!s) return false;
k.$instr.stop(true,true).slideUp(function(){
k.$instr.slideDown().children('.instr').html(s).show();
});
return;
});
k.row = {};
k.clone = (function(){
k.$rows.each(function(){
k.row[$(this).attr('id')] = $(this).contents().clone();
});
});
k.init = (function(){
k.on = false;
k.b = $("#keyboard");
k.$rows = $("#keyboard ul");
k.$instr = $("#instr");
k.$put = $("#keyput");
$(document).trigger('keyboard');
k.clone();
k.lo = layout(doc);
k.lo.track();
});
k.layout = (function(){
k.lo && k.lo.set && k.lo.set();
});
return k;
});r=r();
return r;
});
return key;
})());

928
deps/theory.js vendored
View File

@ -1,928 +0,0 @@
/** THEORY **/
;var theory=theory||null;if(theory){root.init()}else{
theory=(function(b,c,fn){
function theory(b,c){
var a = (function(b,c){
var a = a||theory, l = arguments.length;
if(l == 1){
if(a.text.is(b)){
return a.obj.get(a,b);
}
} if(l == 2){
if(a.text.is(c)){
return a.obj.get(b,c);
}
}
});
if(this && theory.bi.is(this)){ return theorize(a) }
return a(b,c);
} var $, _;
function theorize(a){
var $=undefined,_=undefined;
a.log = (function(s){
//console.log(s);
return a.log;
});
a.fns = (function(){
function fns($){
fns.$_ = $ !== undefined? $ : _;
return fns;
} var $;
fns.is = (function(fn){
$ = fns.$_;fns.$_=_;fn = $||fn;
return (fn instanceof Function)? true : false;
});
fns.flow = (function(s,f){ // TODO: BUG: Seriously reconsider then().done() because they fail on .end() after a synchronous callback, provide no doc or support for it until you do.
var t = (function(){
var args = a.list.slit.call(arguments,0), n;
args.push(t);
n = (function(){
(t.list[t.i++] || t.end).apply(t,args);
})();
return t;
}), list = a.list.is(s)? s : a.list.is(f)? f : 0;
f = a.fns.is(f)? f : a.fns.is(s)? s : function(){};
t.end = list? f : function(){}; // TODO: Receives `next` as param, is this desirable?
t.then = (function(fn){
if(a.fns.is(fn)){ t.list.push(fn) }
return t;
});
t.done = (function(fn){
t.end = a.fns.is(fn)? fn : t.end;
return t;
});
t.list = list || [];
t.i = 0;
if(list){ t() }
else{ f(t) }
return t;
});
fns.sort = (function(args){
if(!args){ return {e:"Empty"} }
var args = a.list.slit.call(args, 0), r = {b:[],n:[],t:[],l:[],o:[],f:[]};
for(var i = 0; i < args.length; i++){
if (fns.is(args[i])){
r.f.push(args[i]);
} else if(a.list.is(args[i])){
r.l.push(args[i]);
} else if(a.obj.is(args[i])){
r.o.push(args[i]);
} else if(a.num.is(args[i])){
r.n.push(args[i]);
} else if(a.text.is(args[i])){
r.t.push(args[i]);
} else if(a.bi.is(args[i])){
r.b.push(args[i]);
}
}
return r;
});
fns.$ = (function(t,v){
v = t.$;
t.$=_;
return v;
});
fns.pass = (function(fn,o){
$ = fns.$_;fns.$_=_;if($){ o=fn;fn=$ }
if(a.text.is(o)){ var tmp = a(fn,o); o = fn; fn = tmp }
if(!fns.is(fn)){ return _ }
return (function(){
return fn.apply(o, a.list.slit.call(arguments));
});
});
return fns;
})();
a.list = (function(){
function list($){
list.$ = $ !== undefined? $ : _;
return list;
} var $;
list.is = (function(l){
l = a.fns.$(list)||l;
return (l instanceof Array)? true : false;
});
list.slit = Array.prototype.slice;
list.at = (function(l,i,opt){
var r;
if($=a.fns.$(list)){ opt=i;i=l;l=$ }
if(!l||!i){ return undefined }
if(a.text.is(l)){ l = l.split('') }
if(i < 0){
r = l.slice().reverse();
i = Math.abs(i);
} opt = opt || {};
if(opt.ebb){
for(--i; 0 <= i; i--){ // upgrade to functionalize
if(r && r[i] !== undefined){ return r[i] }
else if(l[i] !== undefined){ return l[i] }
} return undefined;
}
return (r||l)[--i];
});
list.ify = (function(l,opt){
if($=a.fns.$(list)){ opt=l;l=$ }
opt=opt||{};
opt.wedge = opt.wedge||':';
opt.split = opt.split||',';
var r = [];
if(a.list.is(l)){
return l;
} else
if(a.text.is(l)){
var r = new RegExp("\\s*\\"+opt.split+"\\s*",'ig');
return l.split(r);
} else
if(a.obj.is(l)){
a.obj(l).each(function(v,i){
r.push(i+opt.wedge+(a.obj.is(v)? a.text.ify(v) : v));
});
}
return r;
});
list.fuse = (function(l){
var args = a.list.slit.call(arguments, 0), ll;
l = ($=a.fns.$(list))||l;
ll = $? a.fns.sort(args).l : a.fns.sort(args).l.slice(1);
return Array.prototype.concat.apply(l,ll);
});
list.union = list.u = (function(l,ll){ //[1,2,3,4,5] u [3,5,6,7,8] = [1,2,3,4,5,6,7,8]
return not_implemented_yet;
if($=a.fns.$(list)){ ll=l;l=$ }
// yeaaah, try again.
return r;
});
list.intersect = list.n = (function(l,ll){ //[1,2,3,4,5] n [3,5,6,7,8] = [3,5]
return not_implemented_yet;
if($=a.fns.$(list)){ ll=l;l=$ }
// yeaah, try again.
});
list.less = (function(l,s){ // ToDo: Add ability to use a function to determine what is removed.
var args = a.list.slit.call(arguments, 0), sl = s, ls = l;
l = ($=a.fns.$(list))||l;
s = $? args : args.slice(1);
if($ === args.length){ l=ls;s=sl }
sl = s.length;
return a.list(l).each(function(v,i,t){
if(1 == sl && a.test.is(v,s[0])){ return } else
if(a.list(s).each(function(w,j){
if(a.test.is(v,w)){ return true }
})){ return }
t(v);
})||[];
});
list.each = list.find = (function(l,c,t){
if($=a.fns.$(list)){ t=c;c=l;l=$ }
return a.obj.each(l,c,t);
});
list.copy = (function(l){
return a.obj.copy( ($=a.fns.$(list))||l );
});
list.index = 1;
return list;
})();
a.obj = (function(){
function obj($){
obj.$ = $ !== undefined? $ : _;
return obj;
} var $;
obj.is = (function(o){
o = a.fns.$(obj)||o;
return (o instanceof Object && !a.list.is(o) && !a.fns.is(o))? true : false;
});
obj.ify = (function(o){
o = a.fns.$(obj)||o;
if(a.obj.is(o)){ return o }
try{
o = JSON.parse(o);
}catch(e){o={}};
return o;
});
obj.empty = (function(o){
if(!(o = a.fns.$(obj)||o)){ return true }
return obj.each(o,function(v,i){
if(i){ return true }
})? false : true;
});
obj.copy = (function(o,r,l){
if(!r){
o = a.fns.$(obj) || o;
} l = a.list.is(o);
if(r && !a.obj.is(o) && !l){ return o }
r = {}; o = a.obj.each(o,function(v,i,t){
l? t(obj.copy(v,true)) : (r[i] = obj.copy(v,true));
})||[];
return l? o : r;
});
obj.union = obj.u = (function(x,y){
var args = a.list.slit.call(arguments, 0), r = {};
if($=a.fns.$(obj)){ y=x;x=$ }
if(a.list.is(x)){ y = x } else
if(a.list.is(y)){ } else {
y = $? args : args.slice(1);
y.splice(0,0,x);
}
a.list(y).each(function(v,i){
a.obj(v).each(function(w,j){
if(a.obj(r).has(j)){ return }
r[j] = w;
});
});
return r;
});
obj.has = (function(o,k){
if($=a.fns.$(obj)){ k=o;o=$ }
return Object.prototype.hasOwnProperty.call(o, k);
});
obj.each = (function(l,c,_){
if($=a.fns.$(obj)){ _=c;c=l;l=$ }
var i = 0, ii = 0, x, r, rr, f = a.fns.is(c),
t = (function(k,v){
if(v !== undefined){
rr = rr || {};
rr[k] = v;
return;
} rr = rr || [];
rr.push(k);
});
if(a.list.is(l)){
x = l.length;
for(;i < x; i++){
ii = (i + a.list.index);
if(f){
r = _? c.call(_, l[i], ii, t) : c(l[i], ii, t);
if(r !== undefined){ return r }
} else {
if(a.test.is(c,l[i])){ return ii }
}
}
} else if(a.obj.is(l)){
for(i in l){
if(f){
if(a.obj(l).has(i)){
r = _? c.call(_, l[i], i, t) : c(l[i], i, t);
if(r !== undefined){ return r }
}
} else {
if(a.test.is(c,l[i])){ return i }
}
}
}
return f? rr : a.list.index? 0 : -1;
});
obj.get = (function(o,l,opt,f){
if($=a.fns.$(obj)){ l=o;o=$ }
if(a.num.is(l)){ l = a.text.ify(l) }
if(a.list.is(l)){ l = l.join('.') }
if(a.text.is(l)){
f = (l.length == (l = l.replace(a.text.find.__.fn,'')).length)?
undefined : function(){}; l = l.split(a.text.find.__.dot);
} if(!l){ return }
var x = (l||[]).length, r,
deep = (function(o,v){
return a.list(o).each(function(w,j){
if(a.obj(w||{}).has(v)){ return w }
if(a.list.is(w)){ return deep(w,v) }
});
}), get = (function(v,i,t,n){
if(a.list.is(o)){
if(/^\-?\d+$/.test(v)){
n = a.list.index;
v = a.num.ify(v);
} else {
o = deep(o,v);
}
}
if(n || a.obj(o||{}).has(v)){
o = n? a.list(o).at(v) : o[v];
if(i === x - (a.list.index? 0 : 1)){
return f? a.fns.is(o)? o : f : o;
} return;
}
return f || a.test.nil;
}); r = a.list(l).each(get);
return r === a.test.nil? undefined : r;
});
return obj;
})();
a.text = (function(){
function text($){
text.$ = $ !== undefined? $ : _;
return text;
} var $;
text.is = (function(t){
t = (($=a.fns.$(text))!==_)?$:t;
return typeof t == 'string'?true:false;
});
text.get = (function(q){ return });
text.ify = (function(t){
t = (($=a.fns.$(text))!==_)?$:t;
if(JSON){ return JSON.stringify(t) }
return t.toString? t.toString():t;
});
text.random = text.r = (function(l,c){
if($=a.fns.$(text)){ c=l;l=$ } var $ = $||l, s = '';
l = a.num.is($)? $ : a.num.is(c)? c : 16;
c = a.text.is($)? $ : a.text.is(c)? c : '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz';
while(l>0){ s += c.charAt(Math.floor(Math.random()*c.length)); l-- }
return s;
});
text.clip = (function(t,r,s,e){
if($=a.fns.$(text)){ e=s;s=r;r=t;t=$ } // IE6 fails if e === undefined with Mocha
return t = (t||'').split(r), t=a.num.is(e)?t.slice(s,e):t.slice(s), t.join(r);
});
text.find = (function(t){
var regex = {};
a.log(regex.name = t.name+'.find');
regex.is = /[\.\\\?\*\[\]\{\}\(\)\^\$\+\|\,]/ig
regex.special = {'.':1,'\\':1,'?':1,'*':1,'[':1,']':1,'{':1,'}':1,'(':1,')':1,'^':1,'$':1,'+':1,'|':1,',':1}
regex.mail = /^(("[\w-\s]+")|([\w-]+(?:[\.\+][\w-]+)*)|("[\w-\s]+")([\w-]+(?:[\.\+][\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i;
regex.base64 = new RegExp("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$");
regex.list = /(,\s|;\s|,|;|\s)/ig;
regex.css = /(.+?):(.+?);/ig;
regex.url = /[-a-zA-Z0-9@:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&//=]*)?/gi;
regex.ext = /\.([^\.]+)$/i;
regex.ws_ = /\-/ig;
regex.space = /\s/ig;
regex.num = /(\-\d+\.\d+|\d+\.\d+|\-\d+|\d+)/g;
regex['int'] = /(\-\d+|\d+)/g;
regex.__ = { fn: /\-\>$/, dot: /\./ };
return regex;
})(text);
text.caps = (function(t){
t = a.fns.$(text)||t;
t = (text.is(t))?t:"";
return t.toUpperCase();
});
text.low = (function(t){
t = a.fns.$(text)||t;
t = (text.is(t))?t:"";
return t.toLowerCase();
});
return text;
})();
a.num = (function(){
function num($){
num.$ = ($ !== undefined? $ : _);
return num;
} var $;
num.is = (function(n){
n = (($=a.fns.$(num))!==_)?$:n;
return ( (n===0)? true : (!isNaN(n) && !a.bi.is(n) && !a.list.is(n) && !a.text.is(n))? true : false);
});
num.i = (function(n){return parseInt(a.fns.$(num)||n,10)});
num.dec = (function(n){return parseFloat(a.fns.$(num)||n)});
num.ify = (function(n,o){
if(($=a.fns.$(num))!==_){ o=n;n=$ }
var r, l = a.list.is(o);
if(a.list.is(o)){
if(a.num.is(n)){
return [n];
} if(a.text.is(n)){
r = n.match(a.text.find.num) || [];
return a.list(r).each(function(v,i,t){
t(a.num.ify(v));
});
}
}
r = num.dec(n);
if(a.num.is(r)){ return r }
if(!n){ return }
if(a.text.is(n)){
return a.num.ify( (n.match(a.text.find.num)||[])[0] );
}
});
num.random = num.r = (function(l){
l = ((($=a.fns.$(num))!==_)?$:l)||6;
if(a.list.is(l)){ return (Math.floor(Math.random() * (l[1] - l[0] + 1)) + l[0]) }
l = (l<=14)? l : 14;
var n = '9';
for(var i = 0; i < l-1; i++){ n += '0' }
n = a.num.ify(n);
var r = function(){return Math.floor(Math.random()*10)||(l==1?0:r())};
n = Math.floor(r() + Math.pow(Math.random(),Math.random()) * (n));
if(n.toString().length != l){ return num.r(l) }
return n;
});
return num;
})();
a.bi = (function(){
function bi($){
bi.$ = $ !== undefined? $ : _;
return bi;
} var $;
bi.is = (function(b){
b = (($=a.fns.$(bi))!==_)?$:b;
return (b instanceof Boolean || typeof b == 'boolean')?true:false;
});
return bi;
})();
a.on = (function(){
function on($){
on.$ = $ !== undefined? $ : _;
return on;
} var $, events = {}, sort = (function(A,B){
if(!A || !B){ return 0 } A = A.i; B = B.i;
if(A < B){ return -1 }else if(A > B){ return 1 }
else { return 0 }
});
on.emit = (function(){
if(!a.text.is($ = a.fns.$(on))) return;
var e = events[$] = events[$] || (events[$] = []), args = arguments;
if(!(events[$] = a.list(e).each(function(hear, i, t){
if(!hear.fn) return; t(hear);
hear.fn.apply(hear, args);
}))){ delete events[$]; }
});
on.event = (function(fn, i){
if(!a.text.is($ = a.fns.$(on))) return;
var $ = events[$] = events[$] || (events[$] = [])
, e = {fn: fn, i: i || 0, off: function(){ return !(e.fn = false); }};
return $.push(e), $.sort(sort), e;
});
return on;
})();
a.time = (function(){
function time($){
time.$ = $ !== undefined? $ : _;
return time;
}
time.is = (function(t){
t = ($=a.fns.$(time))||t;
return t? t instanceof Date : (+new Date().getTime());
});
time.now = (function(){
var n = a.num.ify((a.time.is().toString())+'.'+a.num.r(4));
return (theory.time.now.last||0) < n? (theory.time.now.last = n) : time.now();
});
time.loop = (function(fn,d){
var args = a.fns.sort(a.list.slit.call(arguments, 0));
return (args.f.length)?setInterval(a.list(args.f).at(1),a.list(args.n).at(1)):_;
});
time.wait = (function(fn,d){
var args = a.fns.sort(a.list.slit.call(arguments, 0));
return (args.f.length)?setTimeout(a.list(args.f).at(1),a.list(args.n).at(1)):_;
});
time.stop = (function(i){
i = ($=a.fns.$(time))||i;
return (clearTimeout(i)&&clearInterval(i))||true;
});
return time;
})();
a.com = (function($){
var com = a.com;
com.$ = $ !== undefined? $ : _;
com.way = com.way||$;$=_;
com.queue = [];
theory.com.queue = theory.com.queue||[];
com.dc = [theory.time.now()];
com.node = (function(opt){
if(!process._events){ process._events = {} }
if(process.send && !process._events.theory){
process._events.theory = (function(m){
com.msg(a.obj.ify(m));
}); process.on('message',process._events.theory);
process.send({onOpen:{readyState:(process.readyState = 1)},mod:module.theory[opt.way]});
com.wire = process;
return;
}
});
com.page = (function(){
com.src = com.src||(window.location.protocol +'//'+ window.location.hostname)
+ ((window.location.port)?':'+window.location.port:'')
+ (com.path||'/com');
var municate = (function(){
if(!window.SockJS){ return }
theory.com.wire = new window.SockJS(com.src);
theory.com.wire.onopen = function(){
theory.com.open&&theory.com.open();
console.log("Communication initiated at "+com.src+" with "+com.wire.protocol+".");
com.drain();
};
theory.com.wire.onmessage = theory.com.municate||function(m){
var fn, m = a.obj.ify(m.data||m);
if(fn = theory.com.asked[m.when]){
if(a.fns.is(fn)){ fn(m) }
delete theory.com.asked[m.when];
return;
}
com.msg(m);
};
theory.com.wire.onclose = function(m){
console.log('close');
theory.com.close&&theory.com.close(m);
};
});
if(theory.com.off || root.opts.com === false){ return }
if(window.SockJS){
municate();
} else {
module.ajax.load(com.url||(location.local+'//cdn.sockjs.org/sockjs-0.3.min.js')
,function(d){municate()});
}
});
com.drain = (function(){
while(theory.com.queue.length > 0){
com.write(theory.com.queue.shift());
}
});
com.write = (function(m,c){
c = c||theory.com.wire;
if(!c || c.readyState !== 1){
theory.com.queue.push(m);
return;
}
if(a.obj.is(m)){
m = a.text(m).ify();
}
//console.log("send --> "+m);
c.send(m);
});
com.init = (function(c){
if(root.node){ com.node({way:c}) }
if(c){ return }
if(root.page){ com.page() }
return com;
});
/** Helpers **/
com.msg = (function(m,c){
theory.obj.get(theory,theory.obj.get(m,'how.way')+'->')(m,c);
});
com.ways = (function(m,w){
var way = w||a.obj.get(m,'how.way')||com.way;
if($=a.fns.$(com)){
way = ($.charAt(0)=='.')?com.way+$:$;
} return m = com.meta(m,way);
});
com.ask = (function(m,f){
if(!a.fns.is(f)){ return }
m = com.ways(m);
delete m.where;
theory.com.asked[m.when] = f;
com.write(m);
});theory.com.asked = theory.com.asked||{};
com.reply = (function(m){
m = com.ways(m);
if(m.how.web){
m.how.way = 'web.reply';
} m.who = m.who||{};
m.who.to = m.who.to||m.who.tid;
com.write(m);
});
com.send = (function(m){
m = com.ways(m);
com.write(m);
});
com.meta = (function(m,opt){
if(!a.obj.is(m)){ m = {what:m} }
var n = {what: (m.what = m.what||{}) };
opt = opt||{c:{}};
if(a.text.is(opt)){ opt = {w:opt,c:{}} }
if(opt.protocol){ opt.c = opt }
a.obj(m).each(function(v,i){
if( i == 'how' || i == 'who' || i == 'what' ||
i == 'when'|| i == 'where'){ return }
n.what[i] = m.what[i] = v; delete m[i];
});
if(!m.how){ n.how={way: opt.w||com.way} }else{
n.how = m.how;
n.how.way = opt.w||m.how.way||com.way;
delete m.how;
} m.how = n.how;
if(!m.when){ n.when=a.time.now() }else{
n.when = m.when;
delete m.when;
} m.when = n.when;
if(!m.who){
if(root.page && !com.who){
n.who = { tid: (com.who=root.who) }
} if(root.node){ n.who = {} }
}else{
if(a.obj.is(m.who)){ n.who=m.who }else{
n.who = {to: m.who}
} if(root.node){
} if(root.page && !com.who){
n.who.tid = com.who = root.who;
} delete m.who;
} m.who = n.who;
if(!m.where){
if(root.page){ if(a.text.is(m.where)){}else{};
} if(root.node){ n.where={pid: process.pid} }
}else{
if(a.obj.is(m.where)){ n.where = m.where }else{
n.where = {at: m.where};
} if(root.node){
if(!a.obj(m.where).has('pid')){ n.where.pid=process.pid }
} delete m.where;
} m.where = n.where;
return n;
}); /** END HELPERS **/
return com;
});
a.test = (function(){
function test($){
if($===undefined && a.fns.is(test.$)){ try{return test.$()}catch(e){return e} }
test.$ = arguments.length? $ : test.nil;
return test;
} test.nil = test.$ = 'ThEoRy.TeSt.NiL-VaLuE';
test._ = (function(r){ r = a.fns.$(test); test.$ = test.nil; return r; });
test.of = (function(t,f){
if(($=test._()) !== test.nil){ f=t;t=$ }
return t instanceof f;
});
test.is = (function(a, b, aStack, bStack){ // modified Underscore's to fix flaws
if(($=test._()) !== test.nil){ b=a;a=$ }
var _ = {isFunction:theory.fns.is
,has:theory.obj.has}, eq = test.is;
aStack = aStack||[]; bStack = bStack||[];
// Identical objects are equal. `0 === -0`, but they aren't identical.
if(a === b){ return a !== 0 || 1 / a == 1 / b }
if(a == null || b == null){ return a === b }
var className = Object.prototype.toString.apply(a);
if(className != Object.prototype.toString.apply(b)){ return false }
switch(className){
case '[object String]': return a == String(b);
case '[object Number]': return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
case '[object Function]': return a.name === b.name && a.toString() === b.toString();
case '[object Date]':
case '[object Boolean]': return +a == +b;
case '[object RegExp]': return a.source == b.source && a.global == b.global &&
a.multiline == b.multiline && a.ignoreCase == b.ignoreCase;
}
if(typeof a != 'object' || typeof b != 'object'){ return false }
var length = aStack.length;
while(length--){ if(aStack[length] == a){ return bStack[length] == b} }
aStack.push(a); bStack.push(b);
var size = 0, result = true;
if(className == '[object Array]'){
size = a.length; result = size == b.length;
if(result){
while(size--){
if(!(result = eq(a[size], b[size], aStack, bStack))){ break }
}
}
}else{
var aCtor = a.constructor, bCtor = b.constructor;
if(aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
_.isFunction(bCtor) && (bCtor instanceof bCtor))){ return false }
for(var key in a){
if(_.has(a, key)){
size++;
if(!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))){ break }
}
} if(result){
for(key in b){
if(_.has(b, key) && !(size--)){ break }
} result = !size;
}
}
aStack.pop(); bStack.pop();
return result;
});
return test;
})();
return a;
}
theory.Name = 'theory';
theory.version = 2.5;
theorize(theory);
return theory;
})(true);
/**
BASE
**/
(function(r){
var root = root||{}, a = theory;
root.opts = root.opts || {};
root.deps = {loaded:{},alias:{},all:{},wait:{}};
root.pollute = ((typeof GLOBAL !== 'undefined' && GLOBAL.global && GLOBAL.process &&
GLOBAL.process.env && GLOBAL.process.pid && GLOBAL.process.execPath)?
(function(){
global.node = root.node = true;
global.opts = root.opts;
global.theory = theory;
module.theory = module.theory||{}
process.env.totheory = __filename;
if(process.env.NODE_ENV==='production'){process.env.LIVE = true};
module.path = require('path');
require.sep = module.path.sep;
module.exports=(function(cb,deps,name){
if(!arguments.length) return theory;
var args = a.fns.sort(a.list.slit.call(arguments, 0)), r
,m = util.require.apply({},arguments);
args.file = root.submodule||(module.parent||{}).filename;
global.aname = global.aname||m.name;
a.obj(util.deps(m.dependencies,{flat:{},src:args.file})).each(function(name,path){
var p = require(root.submodule=path=util.resolve(path,path));
m.theory[name] = (theory.obj.is(p) && theory.obj.empty(p))? undefined : p;
});
module.theory[m.name] = a.obj.ify(a.text.ify(m));
var mod = (theory[m.name] = m.init(m.theory));
if(global.aname === m.name && theory.com) theory.com(theory.Name).init(m.name);
return mod;
});
return;
}) : (function(){
root = window.root = window.root||root;
root.page = true;
root.who = root.who||a.list((document.cookie+';').match(/tid=(.+?);/)||[]).at(-1)||'';
window.console = window.console||{log:function(s){return s}};
console.saw = (function(s){console.log(a.text(s).ify())});
location.local=(location.protocol==='file:'?'http:':'');
var noConflict={__dirname: window.__dirname,module:window.module,exports:window.exports,require:window.require};
window.__dirname = '';
window.module = {exports: (window.exports = {})};
window.module.ajax = {load:(function(b,c){
var d=document,j="script",s=d.createElement(j); module.sync=(s.onload===null||!s.readyState)?0:1; // IE6+
var e=2166136261,g=b.length,h=c,i=/=\?/,w=window.setTimeout,x,y,a=function(z){
document.body&&(z=z||x)&&s&&document.body[z]?document.body[y=z](s):w(a,0);
};if(i.test(b)){for(;g--;)e=e*16777619^b.charCodeAt(g);
window[j+=e<0?-e:e]=function(){h.apply(h,arguments);delete window[j]};b=b.replace(i,"="+j);c=0
};s.onload=s.onreadystatechange=function(){if(y&&/de|m/.test(s.readyState||"m")){
c&&c();a(x='removeChild');try{for(c in s)delete s[c]}catch(b){}
}};s.src=b;c&&a(x='appendChild');
})};module.ajax.load('#');
window.module.ajax.code = util.load;
window.onerror = (function(e,w,l){
console.log(e + " at line "+ l +" on "+ w);
//if(theory.com){ theory.com.send({e:e,url:w,line:l}) }
});
window.require = module.require = function require(p){
if(!p){ return require }
if(util.stripify(p) == util.stripify(theory.Name)){
return util.require;
} var fn, c = 0, cb = function(f){ fn = f; };
theory.list((p = theory.list.is(p)? p : [p])).each(function(v){
window.module.ajax.code(v,function(d){++c && (p.length <= c) && fn && fn(d)});
}); return cb;
}; window.require.sep = '/'; require.resolve = util.resolve; require.cache = {};
util.init();
if(root.opts.amd === false){theory.obj(noConflict).each(function(v,i){window[i]=v});}
if(theory.com){ theory.com(theory.Name).init() }
})
);
var util = {};
util.theorize = (function(mod){
mod.theory = theory.call(true);
if(mod.theory.com){ mod.theory.com(mod.name) }
return mod.theory;
});
util.require = (function(){
var mod, args = a.fns.sort(a.list.slit.call(arguments,0))
, fail = {name:'fail',init:(function(){console.log('module failed to load')})};
if(args.o.length === 1 && !args.t.length && !args.l.length){
mod = a.list(args.o).at(1);
} else {
if(args.f.length){
mod = {
name: a.list(args.t).at(1)
,init: a.list(args.f).at(1)
,dependencies: a.list(args.l).at(1) || a.list(args.o).at(1)
}
}
} mod.name = mod.name||fail.name;
mod.init = mod.init||mod.main||mod.start||mod.boot||mod.cb||mod.fn||fail.init;
mod.dependencies = mod.dependencies||mod.require||mod.deps||mod.dep;
mod.dependencies = a.list.is(mod.dependencies)?
a.list(mod.dependencies).each(function(v,i,t){t(v,1)}) : mod.dependencies;
mod.theory = util.theorize(mod);
if(root.node){ return mod }
args = {cb:function(p, opt){
if(args.launched
|| a.list(util.deps(mod.dependencies,{flat:{}})).each(function(v,j){
if(!(i = root.deps.loaded[j])){ return true }
if(i === 2){ return true }
if(i && i.launch && a.text.is(v) && mod.theory[v] === undefined){ mod.theory[v] = i.launch; }
})){ return }
args.on.off();
args.launched = {launch: (theory[mod.name] = mod.init(mod.theory||theory)), n:mod.name};
module.exports = exports = args.launched.launch;
if(mod.src){
root.deps.loaded[mod.src] = args.launched;
theory.on('ThEoRy_DePs').emit();
} return args.launched.launch;
}}; args.on = theory.on('ThEoRy_DePs').event(args.cb);
args.start = function(){util.deps(mod.dependencies,args); return args.cb()}
args.name = function(src){
module.on = args.name = false;
root.deps.alias[args.src = mod.src = src] = mod.name;
if((root.deps.all[src] = mod.dependencies)){
root.deps.loaded[src] = 2;
} if(!window.JSON){module.ajax.load(root.opts.JSON||location.local // JSON shim when needed
+"//ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js",args.start)
} else { return args.start() };
}; module.on = (!(require||{}).ing)? args.name(util.src(1))||false : args.name;
});
util.deps = (function(deps, opt){
opt = opt || {};
a.obj(deps).each(function(v,i){
var path = i, dopt = {p:i};
if(opt.src){
delete deps[i];
deps[path = util.resolve(opt.src, util.pathify(path))] = v;
} if(a.list.is(v)){
delete deps[i];
v = deps[path] = a.list(v).each(function(w,i,t){t(util.resolve(opt.src,util.pathify(w)),1)})
} if(a.obj.is(v)){
dopt.defer = v;
opt.flat && util.deps(v,{flat: opt.flat});
} if(v && a.text.is(v)){
dopt.name = v;
} if(opt.flat){
var url = util.urlify(util.pathify(path));
if((i = opt.flat[url]) && i !== 1){ return }
opt.flat[url] = (opt.sub? 1 : dopt.name) || util.stripify(path);
if(i !== 1 && url && a.text.is(url) && (v = root.deps.all[url])){
(a.obj.is(v) || a.list.is(v)) && util.deps(v,{flat: opt.flat, sub:1});
} return;
} return util.load(path, dopt);
});
return opt.flat;
});
util.urlify = (function(url){ // via SO, IE6+ safe
if(!root.page){ return url; }
var el= document.createElement('div');
el.innerHTML= '<a href="'+url+'">x</a>';
return el.firstChild.href;
});
util.pathify = (function(p){
if(!root.page){ return p; }
return p = (/\.js$/i.test(p))? p : p+'.js';
});
util.stripify = (function(p){
if(!a.text.is(p)){ return ''; } p=p.replace(/^\./,'');
return (p.split(require.sep).reverse()[0]).replace(/\.js$/i,'');
});
util.resolve = (function(p1, p2){ // via browserify
if('.' != p2.charAt(0)){ return p2.replace('/',require.sep) }
var path = p1.replace('/',require.sep).split(require.sep)
, segs = p2.replace('/',require.sep).split(require.sep)
path.pop();
for(var i=0;i<segs.length;i++){
var seg = segs[i];
if('..' == seg){ path.pop() }
else if('.' != seg){ path.push(seg) }
} return path.join(require.sep);
});
util.load = (function(p, opt ,z){
if(util.stripify(p) == util.stripify(theory.Name)){
return util.require;
} opt = opt || {};
{var w=root.deps.wait;if(module.sync){if(!z && !a.obj.empty(w)){
w[p] = opt;if(opt.defer){w=root.deps.wait = a.obj(w).u(opt.defer)}return;
}w[p] = opt;if(opt.defer){w=root.deps.wait = a.obj(w).u(opt.defer)}}}
var path = util.pathify(p), url = util.urlify(path)
, cb = (function(d){
if(false !== d){
console.log(opt.p||p, ' loaded');
root.deps.loaded[url] = 1;
module.on && module.on(url);
theory.fns.is(opt) && opt(d);
} theory.on('ThEoRy_DePs').emit();
!module.sync && opt.defer && util.deps(opt.defer, opt);
{if(module.sync){delete w[p];if(!a.obj(w).each(function(v,i,t){
delete w[i];util.load(i,v,1);return 1;})){w=root.deps.wait = false}}}
}); if(root.deps.loaded[url]
|| root.deps.loaded[url] === 0){
return cb(false);
} root.deps.loaded[url] = 0;
(require||{}).ing=true;
try{window.module.ajax.load(path,cb);}
catch(e){console.log("Network error.")};
console.log('loading', opt.p||p);
});
util.sandbox = (function(s,n){
try{ // via jQuery
(window.execScript || function(s){
window["eval"].call(window, s);
})(s);
}catch(e){
console.log("sandbox fail: "+n);
console.log(e, s);
}
});
util.theorycount = 0;
util.src = (function(){
var s = document.getElementsByTagName('script');
s = (s[s.length-1]||{}).src;
return util.stripify(s) === theory.Name? location : s||location;
});
util.init = (function(r){
if(!root.page){ return }
var z='', s = document.getElementsByTagName('script'), t;
for(var i in s){var v = s[i]; // IE6 fails on each, use for instead
r = v.src||r;
if(v.id || !v.innerHTML || util.stripify(v.src)
!== util.stripify(theory.Name)){ false;
} else { t = v }
} if(t){
util.sandbox(t.innerHTML,'Theory Configuration');
t.id = "theory"+util.theorycount++;
}
return r;
});
root.init = (function(){
root.pollute();
return util.init;
})();
})()};

1
examples/Procfile Normal file
View File

@ -0,0 +1 @@
web: node all.js

View File

@ -59,7 +59,7 @@
</li>
</ul>
<script>
var gun = Gun([location + 'gun']);
var gun = Gun([location.origin + '/gun']);
angular.module('admin', []).controller('editor', function($scope){
$scope.data = {};
$scope.$data = gun.load('blob/data').get(function(data){

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="../../gun.js"></script>
<script src="old_gun_for_slinger.js"></script>
</head>
<body><center>
<style>

15
examples/all.js Normal file
View File

@ -0,0 +1,15 @@
console.log("If modules not found, run `npm install` in /example folder!"); // git subtree push -P examples heroku master
var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || 8888;
var express = require('express');
var app = express();
var Gun = require('gun');
var gun = Gun({
s3: (process.env.NODE_ENV === 'production')? null : require('../test/shotgun') // replace this with your own keys!
});
gun.attach(app);
app.use(express.static(__dirname)).listen(port);
console.log('Server started on port ' + port + ' with /gun');

View File

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html ng-app="admin">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.js"></script>
<script src="../../gun.js"></script>
</head>
<body ng-controller="editor">
<style>
html, body {
font-family: Verdana, Geneva, sans-serif;
}
a {
color: skyblue;
text-decoration: none;
cursor: poiner;
}
ul, li {
list-style-type: none;
}
ul:hover, li:hover {
list-style-type: inherit;
}
input {
border: none;
border-bottom: dashed 1px gainsboro;
}
.none {
display: none;
}
</style>
<h3>Admin JSON Editor</h3>
This is a live view of your data, you can edit it in realtime or add new key/values.
<ul name="list">
<li ng-repeat="(key, val) in data">
<div ng-if="key != '_'">
<b>{{key}}</b>:
<span contenteditable="true" gun>{{val}}</span>
</div>
</li>
<li>
<form ng-submit="add()">
<label>
<input ng-model="field" placeholder="key" ng-submit="add()">
<a ng-click="add()">add</a>
<input type="submit" class="none"/>
</label>
</form>
</li>
</ul>
<script>
var gun = Gun(location.origin + '/gun');
angular.module('admin', []).controller('editor', function($scope){
$scope.data = {};
$scope.$data = gun.load('blob/data').on(function(data){
Gun.obj.map(data, function(val, field){
if(val === $scope.data[field]){ return }
$scope.data[field] = val;
});
$scope.$apply();
});
$scope.add = function(a,b,c){
$scope.$data.path($scope.field).set( $scope.data[$scope.field] = 'value' );
$scope.field = '';
};
}).directive('gun', function(){
return function(scope, elem){
elem.on('keyup', function(){
scope.$data.path(scope.key).set( scope.data[scope.key] = elem.text() );
});
};
});
</script>
</body>
</html>

View File

@ -2,7 +2,7 @@ var gun = require('gun')({
s3: (process.env.NODE_ENV === 'production')? null : require('../../test/shotgun') // replace this with your own keys!
});
gun.load('email/mark@gundb.io', function(Mark){
gun.load('email/mark@gundb.io').get(function(Mark){
console.log("Hello ", Mark);
this.path('username').set('amark'); // because we hadn't saved it yet!
this.path('cat').get(function(Hobbes){ // `this` is context of the nodes you explore via path

18
examples/hello-world.js Normal file
View File

@ -0,0 +1,18 @@
var Gun = require('gun');
var gun = Gun({
s3: {
key: '', // AWS Access Key
secret: '', // AWS Secret Token
bucket: '' // The bucket you want to save into
}
});
gun.set({ hello: 'world' }).key('my/first/data');
var http = require('http');
http.createServer(function (req, res) {
gun.load('my/first/data', function(err, data){
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(data));
});
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

2
examples/node_modules/gun/index.js generated vendored
View File

@ -1 +1 @@
module.exports = require(__dirname + '/../../../shots');
module.exports = require(__dirname + '/../../../index');

17
examples/package.json Normal file
View File

@ -0,0 +1,17 @@
{
"name": "examples",
"main": "all.js",
"description": "Example gun apps"
, "version": "0.0.1"
, "engines": {
"node": "~>0.6.6"
}
, "dependencies": {
"express": "~>4.9.0",
"gun": "~>0.0.8"
}
, "scripts": {
"start": "node all.js",
"test": "mocha"
}
}

15
examples/todo/index.html Normal file
View File

@ -0,0 +1,15 @@
<html>
<head>
<title>ToDo</title>
</head>
<body>
<h1>
Todo List
</h1>
<form name="sign" action="http://localhost:8888/gun">
<input name="email" placeholder="email">
<input name="password" type="password" placeholder="password">
<input type="submit" name="it" value="sign in or up">
</form>
</body>
</html>

View File

@ -1,4 +0,0 @@
```
curl http://randomuser.coolaj86.com/api?seed=rohkevus&results=50000 \
-o users.json
```

View File

@ -1,43 +0,0 @@
'use strict';
var users = require('./users.json').results
, Chance = require('chance')
, chance = new Chance(1234)
, b
, d = Date.now()
, num = 50
;
users = users.map(function(user){
user = user.user;
user._ = user._ || {};
user._['#'] = user.sha1;
user.first = user.name.first;
user.last = user.name.last;
user.title = user.name.title;
delete user.name;
user.zip = user.location.zip;
user.street = user.location.street;
user.city = user.location.city;
user.state = user.location.state;
delete user.location;
return user;
})
users = chance.shuffle(users).slice(0, num);
b = chance.shuffle(users.slice(0));
b.forEach(function (user, i) {
if (0 === (i % 100)) {
console.log((Date.now() - d) / 1000, i);
d = Date.now();
}
user.friends = chance.shuffle(users).slice(chance.integer({ min: 20, max: (num < 120)? num : 120 }));
});
var gun = require('gun')({
s3: require('../test/shotgun') // replace this with your own keys!
});
gun.set(b[0]);
console.log(b[1], b[1].friends.length);
console.log((Date.now() - d) / 1000, num);

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
/*!
* Amplify Store - Persistent Client-Side Storage 1.1.0
*
* Copyright 2011 appendTo LLC. (http://appendto.com/team)
* Dual licensed under the MIT or GPL licenses.
* http://appendto.com/open-source-licenses
*
* http://amplifyjs.com
*/
(function(a,b){function e(a,e){c.addType(a,function(f,g,h){var i,j,k,l,m=g,n=(new Date).getTime();if(!f){m={},l=[],k=0;try{f=e.length;while(f=e.key(k++))d.test(f)&&(j=JSON.parse(e.getItem(f)),j.expires&&j.expires<=n?l.push(f):m[f.replace(d,"")]=j.data);while(f=l.pop())e.removeItem(f)}catch(o){}return m}f="__amplify__"+f;if(g===b){i=e.getItem(f),j=i?JSON.parse(i):{expires:-1};if(j.expires&&j.expires<=n)e.removeItem(f);else return j.data}else if(g===null)e.removeItem(f);else{j=JSON.stringify({data:g,expires:h.expires?n+h.expires:null});try{e.setItem(f,j)}catch(o){c[a]();try{e.setItem(f,j)}catch(o){throw c.error()}}}return m})}var c=a.store=function(a,b,d,e){var e=c.type;d&&d.type&&d.type in c.types&&(e=d.type);return c.types[e](a,b,d||{})};c.types={},c.type=null,c.addType=function(a,b){c.type||(c.type=a),c.types[a]=b,c[a]=function(b,d,e){e=e||{},e.type=a;return c(b,d,e)}},c.error=function(){return"amplify.store quota exceeded"};var d=/^__amplify__/;for(var f in{localStorage:1,sessionStorage:1})try{window[f].getItem&&e(f,window[f])}catch(g){}if(window.globalStorage)try{e("globalStorage",window.globalStorage[window.location.hostname]),c.type==="sessionStorage"&&(c.type="globalStorage")}catch(g){}(function(){if(!c.types.localStorage){var a=document.createElement("div"),d="amplify";a.style.display="none",document.getElementsByTagName("head")[0].appendChild(a);try{a.addBehavior("#default#userdata"),a.load(d)}catch(e){a.parentNode.removeChild(a);return}c.addType("userData",function(e,f,g){a.load(d);var h,i,j,k,l,m=f,n=(new Date).getTime();if(!e){m={},l=[],k=0;while(h=a.XMLDocument.documentElement.attributes[k++])i=JSON.parse(h.value),i.expires&&i.expires<=n?l.push(h.name):m[h.name]=i.data;while(e=l.pop())a.removeAttribute(e);a.save(d);return m}e=e.replace(/[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/g,"-");if(f===b){h=a.getAttribute(e),i=h?JSON.parse(h):{expires:-1};if(i.expires&&i.expires<=n)a.removeAttribute(e);else return i.data}else f===null?a.removeAttribute(e):(j=a.getAttribute(e),i=JSON.stringify({data:f,expires:g.expires?n+g.expires:null}),a.setAttribute(e,i));try{a.save(d)}catch(o){j===null?a.removeAttribute(e):a.setAttribute(e,j),c.userData();try{a.setAttribute(e,i),a.save(d)}catch(o){j===null?a.removeAttribute(e):a.setAttribute(e,j);throw c.error()}}return m})}})(),function(){function e(a){return a===b?b:JSON.parse(JSON.stringify(a))}var a={},d={};c.addType("memory",function(c,f,g){if(!c)return e(a);if(f===b)return e(a[c]);d[c]&&(clearTimeout(d[c]),delete d[c]);if(f===null){delete a[c];return null}a[c]=f,g.expires&&(d[c]=setTimeout(function(){delete a[c],delete d[c]},g.expires));return f})}()})(this.amplify=this.amplify||{})

672
gun.js
View File

@ -12,12 +12,66 @@
,HAM: '>'
}
;(function(Gun){
Gun.version = 0.9;
Gun.is = function(gun){ return (gun instanceof Gun)? true : false }
Gun.version = 0.8;
Gun.is.value = function(v){ // null, binary, number (!Infinity), text, or a rel.
if(v === null){ return true } // deletes
if(v === Infinity){ return false } // we want this to be, but JSON does not support it, sad face.
if(Gun.bi.is(v)
|| Gun.num.is(v)
|| Gun.text.is(v)){
return true; // simple values
}
var id;
if(id = Gun.is.soul(v)){
return id;
}
return false;
}
Gun.is.soul = function(v){
if(Gun.obj.is(v)){
var id;
Gun.obj.map(v, function(soul, field){
if(id){ return id = false } // if ID is already defined AND we're still looping through the object, it is invalid.
if(field == Gun._.soul && Gun.text.is(soul)){
id = soul; // we found the soul!
} else {
return id = false; // if there exists anything else on the object, that isn't the soul, then it is invalid.
}
});
if(id){
return id;
}
}
return false;
}
Gun.is.soul.on = function(n){ return (n && n._ && n._[Gun._.soul]) || false }
Gun.is.node = function(node, cb){
if(!Gun.obj.is(node)){ return false }
if(Gun.is.soul.on(node)){
return !Gun.obj.map(node, function(value, field){ // need to invert this, because the way we check for this is via a negation.
if(field == Gun._.meta){ return } // skip this.
if(!Gun.is.value(value)){ return true } // it is true that this is an invalid node.
if(cb){ cb(value, field) }
});
}
return false;
}
Gun.is.graph = function(graph, cb, fn){
var exist = false;
if(!Gun.obj.is(graph)){ return false }
return !Gun.obj.map(graph, function(node, soul){ // need to invert this, because the way we check for this is via a negation.
if(!node || soul !== Gun.is.soul.on(node) || !Gun.is.node(node, fn)){ return true } // it is true that this is an invalid graph.
if(cb){ cb(node, soul) }
exist = true;
}) && exist;
}
// Gun.ify // the serializer is too long for right here, it has been relocated towards the bottom.
Gun.union = function(graph, prime){
var context = Gun.shot();
context.nodes = {};
context('done');context('change');
context('done');
context('change');
Gun.obj.map(prime, function(node, soul){
var vertex = graph[soul], env;
if(!vertex){ // disjoint
@ -91,7 +145,7 @@
Gun.obj.map(delta, function update(deltaValue, field){
if(field === Gun._.meta){ return }
if(!Gun.obj.has(current, field)){ // does not need to be applied through HAM
each.call({incoming: true, converge: true}, current, field, deltaValue);
each.call({incoming: true, converge: true}, current, field, deltaValue); // done synchronously
return;
}
var serverState = Gun.time.is();
@ -99,7 +153,7 @@
var state = HAM(serverState, context.states.delta[field], context.states.current[field], deltaValue, current[field]);
//console.log("HAM:", field, deltaValue, context.states.delta[field], context.states.current[field], 'the', state, (context.states.delta[field] - serverState));
if(state.err){
Gun.log(".!HYPOTHETICAL AMNESIA MACHINE ERR!.", state.err);
console.log(".!HYPOTHETICAL AMNESIA MACHINE ERR!.", state.err);
return;
}
if(state.state || state.quarantineState || state.current){
@ -107,7 +161,7 @@
return;
}
if(state.incoming){
each.call(state, current, field, deltaValue);
each.call(state, current, field, deltaValue); // done synchronously
return;
}
if(state.amnesiaQuarantine){
@ -135,8 +189,12 @@
return Gun.text.random(l, c);
}
Gun.log = function(a, b, c, d, e, f){
//console.log(a, b, c, d, e, f);
//console.log.apply(console, arguments);
var gun = this;
if(!gun || !gun.__ || !gun.__.opt){
return console.log.apply(console, arguments);
}
if(gun.__.opt.quiet){ return }
return console.log.apply(console, arguments);
}
}(Gun));
;(function(Chain){
@ -144,10 +202,9 @@
var gun = this;
gun._ = gun._ || {};
gun.__ = gun.__ || {};
gun.shot = Gun.shot();
gun.shot('then');
gun.shot('err');
if(!opt){ return gun }
gun.shot = Gun.shot('then', 'err');
if(opt === null){ return gun }
opt = opt || {};
gun.__.opt = gun.__.opt || {};
gun.__.keys = gun.__.keys || {};
gun.__.graph = gun.__.graph || {};
@ -159,6 +216,7 @@
gun.__.opt.peers = opt.peers || gun.__.opt.peers || {};
gun.__.opt.uuid = opt.uuid || gun.__.opt.uuid || {};
gun.__.opt.hooks = gun.__.opt.hooks || {};
gun.__.hook = Gun.shot('next','end');
Gun.obj.map(opt.hooks, function(h, f){
if(!Gun.fns.is(h)){ return }
gun.__.opt.hooks[f] = h;
@ -167,7 +225,7 @@
return gun;
}
Chain.chain = function(from){
var gun = Gun();
var gun = Gun(null);
from = from || this;
gun.back = from;
gun.__ = from.__;
@ -179,8 +237,9 @@
}
Chain.load = function(key, cb, opt){
var gun = this.chain();
cb = cb || function(){};
gun.shot.then(function(){ cb.apply(gun, arguments) });
cb = cb || {};
gun.shot('done');
gun.shot.done(function(){
cb.soul = (key||{})[Gun._.soul];
if(cb.soul){
cb.node = gun.__.graph[cb.soul];
@ -189,45 +248,50 @@
cb.node = gun.__.keys[key];
}
if(cb.node){ // set this to the current node, too!
Gun.log("from gun"); // remember to do all the same stack stuff here also!
var freeze = Gun.obj.copy(gun._.node = cb.node);
gun.shot('then').fire(freeze); // freeze now even though internals use this? OK for now.
return gun; // TODO: BUG: This needs to react the same as below!
Gun.log.call(gun, "load via gun"); // remember to do all the same stack stuff here also!
gun._.node = cb.node;
if(Gun.fns.is(cb)){ cb.call(gun, null, Gun.obj.copy(gun._.node)) } // frozen copy
gun.shot('then').fire(gun._.node); // freezing for internal use is NOT okay.
return; // TODO: BUG: This needs to react the same as below! I think this is all done/resolved/clear now.
}
cb.fn = function(){}
// missing: hear shots!
// missing: hear shots! I now hook this up in other places, but we could get async/latency issues?
// We need to subscribe early? Or the transport layer handle this for us?
if(Gun.fns.is(gun.__.opt.hooks.load)){
gun.__.opt.hooks.load(key, function(err, data){
// console.log('loaded', err, data);
gun._.loaded = (gun._.loaded || 0) + 1; // TODO: loading should be idempotent even if we got an err or no data
if(err){ return (gun._.dud||cb.fn)(err) }
if(!data){ return (gun._.blank||cb.fn)() }
if(err){ return cb(err), (gun._.dud||cb.fn)(err) }
if(!data){ return cb(null), (gun._.blank||cb.fn)() }
var context = gun.union(data); // safely transform the data
if(context.err){ return (gun._.dud||cb.fn)(context.err) }
if(context.err){ return cb(context.err), (gun._.dud||cb.fn)(context.err) }
gun._.node = gun.__.graph[data._[Gun._.soul]]; // don't wait for the union to be done because we want the immediate state not the intended state.
if(!cb.soul){ gun.__.keys[key] = gun._.node }
var freeze = Gun.obj.copy(gun._.node);
gun.shot('then').fire(freeze); // freeze now even though internals use this? OK for now.
if(!cb.soul){ gun.__.keys[key] = gun._.node } // TODO: BUG: what if the key has changed since we were gone? What do we resolve to? Not sure yet.
if(Gun.fns.is(cb)){ cb.call(gun, null, Gun.obj.copy(gun._.node)) } // frozen copy
gun.shot('then').fire(gun._.node); // freezing for internal use is NOT okay.
}, opt);
} else {
Gun.log("Warning! You have no persistence layer to load from!");
Gun.log.call(gun, "Warning! You have no persistence layer to load from!");
}
});
gun.shot('done').fire(); // because we are loading, we always fire!
return gun;
}
Chain.key = function(key, cb){
var gun = this;
gun.shot.then(function(){
Gun.log("make key", key);
//Gun.log.call(gun, "make key", key);
cb = cb || function(){};
cb.node = gun.__.keys[key] = gun._.node;
if(!cb.node){ return gun }
if(Gun.fns.is(gun.__.opt.hooks.key)){
gun.__.opt.hooks.key(key, cb.node._[Gun._.soul], function(err, data){
Gun.log("key made", key);
//Gun.log.call(gun, "key made", key);
if(err){ return cb(err) }
return cb(null);
});
} else {
Gun.log("Warning! You have no key hook!");
Gun.log.call(gun, "Warning! You have no key hook!");
}
});
if(!gun.back){ gun.shot('then').fire() }
@ -245,6 +309,8 @@
.path('foo', 'bar').get({foo: foo, bar: bar}) || .path({a: 'foo', b: 'bar'}).get({a: foo, b: bar})
Find via multiple paths where the fields and values must match
.path({foo: val, bar: val}).get({})
Path ultimately should call .get each time, individually, for what it finds.
Things that wait and merge many things together should be an abstraction ontop of path.
*/
Chain.path = function(path){ // The focal point follows the path
var gun = this.chain();
@ -253,19 +319,19 @@
//console.log("shot path", path, node);
gun.field = null;
gun._.node = node;
if(!path.length){ // if the path resolves to another node, we finish here
return gun.shot('then').fire(node); // already frozen from loaded.
if(!path.length){ // if the path resolves to another node, we finish here.
return gun.shot('then').fire(node); // this is not frozen yet, but it is still used for internals so keep it unfrozen.
}
var field = path.shift()
var field = Gun.text.ify(path.shift())
, val = node[field];
gun.field = field;
if(Gun.ify.is.soul(val)){ // we might end on a link, so we must resolve
if(Gun.is.soul(val)){ // we might end on a link, so we must resolve
return gun.load(val).shot.then(trace);
} else
if(path.length){ // we cannot go any further, despite the fact there is more path, which means the thing we wanted does not exist
if(path.length){ // we cannot go any further, despite the fact there is more path, which means the thing we wanted does not exist.
gun.shot('then').fire();
} else { // we are done, and this should be the value we wanted.
gun.shot('then').fire(val); // primitive values are passed as copies in JS.
gun.shot('then').fire(val); // internals use this thus not frozen yet, but primitive values are passed as copies anyways in js.
}
});
// if(!gun.back){ gun.shot('then').fire() } // replace below with this? maybe???
@ -278,18 +344,27 @@
Chain.get = function(cb){
var gun = this;
gun.shot.then(function(val){
cb.call(gun, val); // frozen from done.
gun.__.on(gun._.node._[Gun._.soul]).event(function(delta){
cb.call(gun, Gun.obj.is(val)? Gun.obj.copy(val) : val); // frozen copy
});
return gun;
}
Chain.on = function(cb){
var gun = this;
gun.get(function(node){
var get = this; // I'm not sure what state we're in, or which (get or gun) we should this-ify.
cb.call(gun, Gun.obj.copy(node)); // frozen copy
get.__.on(get._.node._[Gun._.soul]).event(function(delta){
if(!delta){ return }
if(!gun.field){
cb.call(gun, Gun.obj.copy(gun._.node));
if(!get.field){
cb.call(get, Gun.obj.copy(get._.node)); // frozen copy
return;
}
if(Gun.obj.has(delta, gun.field)){
cb.call(gun, delta[gun.field]);
if(Gun.obj.has(delta, get.field)){
delta = delta[get.field];
cb.call(get, Gun.obj.is(delta)? Gun.obj.copy(delta) : delta); // frozen copy
}
})
});
})
return gun;
}
/*
@ -306,44 +381,47 @@
Chain.set = function(val, cb, opt){ // TODO: need to turn deserializer into a trampolining function so stackoverflow doesn't happen.
opt = opt || {};
var gun = this, set;
gun.shot.then(function(){
if(gun.field){ // a field cannot be 0!
gun.shot.then(function(){ // set/key should cause a subscription, is this working yet?
//console.log("chain.set", gun, gun.field, val, gun._.node);
if(gun.field){ // field is always a string
set = {}; // in case we are doing a set on a field, not on a node
set[gun.field] = val; // we create a blank node with the field/value to be set
val = set;
} // TODO: should be able to handle val being a relation or a gun context or a gun promise.
val._ = Gun.ify.soul.call(gun, {}, gun._.node); // and then set their souls to be the same that way they will merge correctly for us during the union!
// TODO: BUG: IF we are setting an object, doing a partial merge, and they are reusing a frozen copy, we need to do a DIFF to update the HAM! Or else we'll get "old" HAM.
val._ = Gun.ify.soul.call(gun, {}, gun._.node || val); // and then set their souls to be the same that way they will merge correctly for us during the union!
cb = Gun.fns.is(cb)? cb : function(){};
set = Gun.ify.call(gun, val);
cb.root = set.root;
if(set.err){ return cb(set.err), gun }
set = Gun.ify.state(set.nodes, Gun.time.is()); // set time state on nodes?
if(set.err){ return cb(set.err), gun }
Gun.union(gun.__.graph, set.nodes); // while this maybe should return a list of the nodes that were changed, we want to send the actual delta
gun.union(set.nodes); // while this maybe should return a list of the nodes that were changed, we want to send the actual delta
gun._.node = gun.__.graph[cb.root._[Gun._.soul]] || cb.root;
// TODO? ^ Maybe BUG! if val is a new node on a field, _.node should now be that! Or will that happen automatically?
if(Gun.fns.is(gun.__.opt.hooks.set)){
gun.__.opt.hooks.set(set.nodes, function(err, data){ // now iterate through those nodes to S3 and get a callback once all are saved
//Gun.log("gun set hook callback called");
gun.__.opt.hooks.set(set.nodes, function(err, data){ // now iterate through those nodes to a persistence layer and get a callback once all are saved
if(err){ return cb(err) }
return cb(null);
});
} else {
Gun.log("Warning! You have no persistence layer to save to!");
Gun.log.call(gun, "Warning! You have no persistence layer to save to!");
}
});
if(!gun.back){ gun.shot('then').fire() }
return gun;
}
// Union is different than set. Set casts non-gun style of data into a gun compatible data.
// Union takes already gun compatible data and validates it for a merge.
// Meaning it is more low level, such that even set uses union internally.
Chain.union = function(prime, cb){
var tmp, gun = this, context = Gun.shot();
context.nodes = {};
var tmp = {}, gun = this, context = Gun.shot();
cb = cb || function(){}
context.nodes = {};
if(!prime){
context.err = {err: "No data to merge!"};
} else
if(prime._ && prime._[Gun._.soul]){
tmp = {};
if(Gun.is.soul.on(prime)){
tmp[prime._[Gun._.soul]] = prime;
prime = tmp;
}
@ -351,31 +429,27 @@
cb(context.err = context.err || {err: "No gun instance!", corrupt: true}, context);
return context;
}
Gun.obj.map(prime, function(node){ // map over the prime graph, to get each node that has been modified
var set = Gun.ify.call(gun, node);
if(set.err){ return context.err = set.err } // check to see if the node is valid
Gun.obj.map(set.nodes, function(node, soul){ // if so, map over it, and any other nodes that were deserialized from it
context.nodes[soul] = node; // into a valid context we'll actually do a union on.
});
});
if(!Gun.is.graph(prime, function(node, soul){
context.nodes[soul] = node;
})){
cb(context.err = context.err || {err: "Invalid graph!", corrupt: true}, context);
return context;
}
if(context.err){ return cb(context.err, context), context } // if any errors happened in the previous steps, then fail.
Gun.union(gun.__.graph, context.nodes).done(function(err, env){ // now merge prime into the graph
context.err = err || env.err;
cb(context.err, context || {});
}).change(function(delta){
if(!delta || !delta._ || !delta._[Gun._.soul]){ return }
gun.__.on(delta._[Gun._.soul]).emit(Gun.obj.copy(delta)); // this is in reaction to HAM
if(!Gun.is.soul.on(delta)){ return }
gun.__.on(delta._[Gun._.soul]).emit(Gun.obj.copy(delta)); // this is in reaction to HAM. frozen copy here?
});
return context;
}
Chain.match = function(){ // same as path, except using objects
return this;
}
Chain.blank = function(blank){
this._.blank = Gun.fns.is(blank)? blank : function(){};
return this;
}
Chain.dud = function(dud){
Chain.err = Chain.dud = function(dud){ // WARNING: dud will be depreciated in favor of err.
this._.dud = Gun.fns.is(dud)? dud : function(){};
return this;
}
@ -383,6 +457,23 @@
;(function(Util){
Util.fns = {};
Util.fns.is = function(fn){ return (fn instanceof Function)? true : false }
Util.fns.sum = function(done){ // combine with Util.obj.map for some easy parallel async operations!
var context = {task: {}, data: {}};
context.end = function(e,v){ return done(e,v), done = function(){} };
context.add = function(fn, id){
context.task[id = id || (Gun.text.is(fn)? fn : Gun.text.random())] = false;
var each = function(err, val){
context.task[id] = true;
if(err){ (context.err = context.err || {})[id] = err }
context.data[id] = val;
if(!Gun.obj.map(context.task, function(val){ if(!val){ return true } })){ // it is true if we are NOT done yet, then invert.
done(context.err, context.data);
}
}, c = context;
return Gun.fns.is(fn)? function(){ return fn.apply({task: c.task, data: c.data, end: c.end, done: each}, arguments) } : each;
}
return context;
}
Util.bi = {};
Util.bi.is = function(b){ return (b instanceof Boolean || typeof b == 'boolean')? true : false }
Util.num = {};
@ -480,7 +571,7 @@
var setImmediate = setImmediate || function(cb){setTimeout(cb,0)}
function Flow(){
var chain = new Flow.chain();
return chain.$ = function(where){
chain.$ = function(where){
(chain._ = chain._ || {})[where] = chain._[where] || [];
chain.$[where] = chain.$[where] || function(fn){
(chain._[where]||[]).push(fn);
@ -489,6 +580,8 @@
chain.where = where;
return chain;
}
Gun.list.map(Array.prototype.slice.call(arguments), function(where){ chain.$(where) });
return chain.$;
}
Flow.is = function(flow){ return (Flow instanceof flow)? true : false }
;Flow.chain=(function(){
@ -516,6 +609,8 @@
return Flow;
}());Gun.shot.chain.chain.fire=Gun.shot.chain.chain.pipe;
;Gun.on=(function(){
// events are fundamentally different, being synchronously 1 to N fan out,
// than req/res/callback/promise flow, which are asynchronously 1 to 1 into a sink.
function On(where){
if(where){
return (On.event = On.event || On.create())(where);
@ -615,7 +710,7 @@
sub.path = sub.path || '';
context = context || {};
context.nodes = context.nodes || {};
if((sub.simple = Gun.ify.is(data)) && !(sub._ && Gun.text.is(sub.simple))){
if((sub.simple = Gun.is.value(data)) && !(sub._ && Gun.text.is(sub.simple))){
return data;
} else
if(Gun.obj.is(data)){
@ -623,12 +718,12 @@
, err = {err: "Metadata does not support external or circular references at " + sub.path, meta: true};
context.root = context.root || value;
if(seen = ify.seen(context._seen, data)){
//Gun.log("seen in _", sub._, sub.path, data);
//Gun.log.call(gun, "seen in _", sub._, sub.path, data);
context.err = err;
return;
} else
if(seen = ify.seen(context.seen, data)){
//Gun.log("seen in data", sub._, sub.path, data);
//Gun.log.call(gun, "seen in data", sub._, sub.path, data);
if(sub._){
context.err = err;
return;
@ -636,7 +731,7 @@
symbol = Gun.ify.soul.call(gun, symbol, seen);
return symbol;
} else {
//Gun.log("seen nowhere", sub._, sub.path, data);
//Gun.log.call(gun, "seen nowhere", sub._, sub.path, data);
if(sub._){
context.seen.push({data: data, node: value});
} else {
@ -648,7 +743,7 @@
Gun.obj.map(data, function(val, field){
var subs = {path: sub.path + field + '.', _: sub._ || (field == Gun._.meta)? true : false };
val = ify(val, context, subs);
//Gun.log('>>>>', sub.path + field, 'is', val);
//Gun.log.call(gun, '>>>>', sub.path + field, 'is', val);
if(context.err){ return true }
if(nothing === val){ return }
// TODO: check field validity
@ -714,47 +809,13 @@
Gun.ify.soul = function(to, from){
var gun = this;
to = to || {};
if(Gun.ify.soul.is(from)){
if(Gun.is.soul.on(from)){
to[Gun._.soul] = from._[Gun._.soul];
return to;
}
to[Gun._.soul] = Gun.roulette.call(gun);
return to;
}
Gun.ify.soul.is = function(o){
if(o && o._ && o._[Gun._.soul]){
return true;
}
}
Gun.ify.is = function(v){ // null, binary, number (!Infinity), text, or a rel.
if(v === null){ return true } // deletes
if(v === Infinity){ return false } // we want this to be, but JSON does not support it, sad face.
if(Gun.bi.is(v)
|| Gun.num.is(v)
|| Gun.text.is(v)){
return true; // simple values
}
var yes;
if(yes = Gun.ify.is.soul(v)){
return yes;
}
return false;
}
Gun.ify.is.soul = function(v){
if(Gun.obj.is(v)){
var yes;
Gun.obj.map(v, function(soul, field){
if(yes){ return yes = false }
if(field === Gun._.soul && Gun.text.is(soul)){
yes = soul;
}
});
if(yes){
return yes;
}
}
return false;
}
}());
if(typeof window !== "undefined"){
window.Gun = Gun;
@ -765,70 +826,70 @@
;(function(tab){
if(!this.Gun){ return }
if(!window.JSON){ Gun.log("Include JSON first: ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js") } // for old IE use
if(!window.JSON){ throw new Error("Include JSON first: ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js") } // for old IE use
Gun.on('opt').event(function(gun, opt){
tab.server = tab.server || function(req, res, next){
}
window.tab = tab; // window.XMLHttpRequest = null; // for debugging purposes
(function(){
tab.store = {};
var store = window.localStorage || {setItem: function(){}, removeItem: function(){}, getItem: function(){}};
tab.store.set = function(key, val){console.log('setting', key); return store.setItem(key, Gun.text.ify(val)) }
tab.store.get = function(key){ return Gun.obj.ify(store.getItem(key)) }
tab.store.del = function(key){ return store.removeItem(key) }
}());
window.tab = tab; // for debugging purposes
opt = opt || {};
tab.headers = opt.headers || {};
tab.headers['gun-tid'] = tab.headers['gun-tid'] || Gun.text.random();
tab.load = tab.load || function(key, cb, opt){
if(!key){ return }
cb = cb || function(){};
opt = opt || {};
opt.url = opt.url || {};
opt.headers = tab.headers;
if(key[Gun._.soul]){
key = '_' + tab.query(key);
opt.url.query = key;
} else {
opt.url.pathname = '/' + key;
}
console.log("gun load", key);
Gun.obj.map(gun.__.opt.peers, function(peer, url){
tab.ajax(url + '/' + key, null, function(err, reply){
request(url, null, function(err, reply){
console.log('via', url, key, reply);
if(!reply){ return } // handle reconnect?
if(err || !reply){ return } // handle reconnect?
if(reply.body && reply.body.err){
cb(reply.body.err);
} else {
cb(null, reply.body);
}
(function(){
tab.subscribe.sub = (reply.headers || {})['gun-sub'] || tab.subscribe.sub;
//console.log("We are sub", tab.subscribe.sub);
var data = reply.body;
if(!data || !data._){ return }
tab.subscribe(data._[Gun._.soul]);
}());
}, {headers: {'Gun-Sub': tab.subscribe.sub || ''}, header: {'Gun-Sub': 1}});
}, opt);
cb.peers = true;
});
if(!cb.peers){ // there are no peers! this is a local only instance
Gun.log.call(gun, "Warning! You have no peers to connect to!");
setTimeout(function(){cb({err: "No peers!"})},0);
}
tab.url = function(nodes){
return;
console.log("urlify delta", nodes);
var s = ''
, uri = encodeURIComponent;
Gun.obj.map(nodes, function(delta, soul){
var ham;
if(!delta || !delta._ || !(ham = delta._[Gun._.HAM])){ return }
s += uri('#') + '=' + uri(soul) + '&';
Gun.obj.map(delta, function(val, field){
if(field === Gun._.meta){ return }
s += uri(field) + '=' + uri(Gun.text.ify(val)) + uri('>') + uri(ham[field]) + '&';
})
}
tab.key = function(key, soul, cb){
var meta = {};
meta[Gun._.soul] = soul = Gun.text.is(soul)? soul : (soul||{})[Gun._.soul];
if(!soul){
return cb({err: "No soul!"});
}
Gun.obj.map(gun.__.opt.peers, function(peer, url){
request(url, meta, function(err, reply){
console.log("gun key done", soul, err, reply);
if(err || !reply){
Gun.log.call(gun, err = err || "Error: Key failed to be made on " + url);
// tab.key(key, soul, cb); // naive implementation of retry TODO: BUG: need backoff and anti-infinite-loop!
cb(err);
} else {
cb();
}
}, {url: {pathname: '/' + key }, headers: tab.headers});
});
console.log(s);
return s;
}
tab.set = tab.set || function(nodes, cb){
cb = cb || function(){};
// TODO: batch and throttle later.
//tab.store.set(cb.id = 'send/' + Gun.text.random(), nodes);
//tab.url(nodes);
console.log("gun set start");
Gun.obj.map(gun.__.opt.peers, function(peer, url){
tab.ajax(url, nodes, function respond(err, reply, id){
request(url, nodes, function respond(err, reply, id){
console.log("gun set done", err, reply, id);
return;
var body = reply && reply.body;
respond.id = respond.id || cb.id;
Gun.obj.del(tab.set.defer, id); // handle err with a retry? Or make a system auto-do it?
@ -853,200 +914,160 @@
}
if(body.reply || body.defer || body.refed){ return }
//tab.store.del(respond.id);
}, {headers: {'Gun-Sub': tab.subscribe.sub || ''}});
}, {headers: tab.headers});
});
Gun.obj.map(nodes, function(node, soul){
gun.__.on(soul).emit(node, true); // should we emit difference between local and not?
});
}
tab.set.defer = {};
tab.subscribe = function(soul){ // TODO: BUG!!! ERROR! Handle disconnection (onerror)!!!!
tab.subscribe.to = tab.subscribe.to || {};
if(soul){
tab.subscribe.to[soul] = 1;
request.createServer(function(req, res){
console.log("client server received request", req);
if(!req.body){ return }
gun.union(req.body);
});
(function(){
tab.store = {};
var store = window.localStorage || {setItem: function(){}, removeItem: function(){}, getItem: function(){}};
tab.store.set = function(key, val){console.log('setting', key); return store.setItem(key, Gun.text.ify(val)) }
tab.store.get = function(key){ return Gun.obj.ify(store.getItem(key)) }
tab.store.del = function(key){ return store.removeItem(key) }
}());
gun.__.opt.hooks.load = gun.__.opt.hooks.load || tab.load;
gun.__.opt.hooks.set = gun.__.opt.hooks.set || tab.set;
gun.__.opt.hooks.key = gun.__.opt.hooks.key || tab.key;
});
var request = (function(){
function r(base, body, cb, opt){
opt = opt || (base.length? {base: base} : base);
opt.base = opt.base || base;
opt.body = opt.body || body;
if(!opt.base){ return }
r.transport(opt, cb);
}
var opt = {
header: {'Gun-Sub': 1},
headers: {
'Gun-Sub': tab.subscribe.sub || ''
r.createServer = function(fn){ (r.createServer = fn).on = true }
r.transport = function(opt, cb){
if(r.ws(opt, cb)){ return }
r.jsonp(opt, cb);
}
}, query = tab.subscribe.sub? '' : tab.query(tab.subscribe.to);
console.log("subscribing poll", tab.subscribe.sub);
Gun.obj.map(gun.__.opt.peers, function(peer, url){
tab.ajax(url + query, null, function(err, reply){
if(err || !reply || !reply.body || reply.body.err){ // not interested in any null/0/''/undefined values
//console.log(err, reply);
r.ws = function(opt, cb){
var ws = window.WebSocket || window.mozWebSocket || window.webkitWebSocket;
if(!ws){ return }
if(ws = r.ws.peers[opt.base]){
var req = {};
if(opt.headers){ req.headers = opt.headers }
if(opt.body){ req.body = opt.body }
if(opt.url){ req.url = opt.url }
r.ws.cbs[req.wsrid = 'WS' + (+ new Date()) + '.' + Math.floor((Math.random()*65535)+1)] = function(err,res){
delete r.ws.cbs[req.wsrid];
cb(err,res);
}
ws.send(JSON.stringify(req));
return true;
}
if(ws === false){ return }
ws = r.ws.peers[opt.base] = new WebSocket(opt.base.replace('http','ws'));
ws.onopen = function(o){ r.ws(opt, cb) };
ws.onclose = function(c){
if(!c){ return }
if(1006 === c.code){ // websockets cannot be used
ws = r.ws.peers[opt.base] = false;
r.transport(opt, cb);
return;
}
console.log("poll", 1 || reply);
tab.subscribe.poll();
if(reply.headers){
tab.subscribe.sub = reply.headers['gun-sub'] || tab.subscribe.sub;
}
if(!reply.body){ return } // do anything?
gun.union(reply.body); // safely transform data
}, opt);
});
}
tab.subscribe.poll = function(){
clearTimeout(tab.subscribe.poll.id);
tab.subscribe.poll.id = setTimeout(tab.subscribe, 1); //1000 * 10); // should enable some server-side control of this.
}
tab.query = function(params){
var s = '?'
, uri = encodeURIComponent;
Gun.obj.map(params, function(val, field){
s += uri(field) + '=' + uri(val || '') + '&';
});
return s;
}
tab.ajax = (function(){
function ajax(url, data, cb, opt){
var u;
opt = opt || {};
opt.header = opt.header || {};
opt.header["Content-Type"] = 1;
opt.headers = opt.headers || {};
if(data === u || data === null){
data = u;
} else {
try{data = JSON.stringify(data);
opt.headers["Content-Type"] = "application/json";
}catch(e){}
}
opt.method = opt.method || (data? 'POST' : 'GET');
var xhr = ajax.xhr() || ajax.jsonp() // TODO: BUG: JSONP push is working, but not post
, clean = function(){
if(!xhr){ return }
xhr.onreadystatechange = xhr.onerror = null;
try{xhr.abort();
}catch(e){}
xhr = null;
}
xhr.onerror = function(){
if(cb){
cb({err: err || 'Unknown error.', status: xhr.status });
}
clean(xhr.status === 200 ? 'network' : 'permanent');
ws = r.ws.peers[opt.base] = null; // this will make the next request try to reconnect
};
xhr.onreadystatechange = function(){
if(!xhr){ return }
var reply, status;
try{reply = xhr.responseText;
status = xhr.status;
}catch(e){}
if(status === 1223){ status = 204 }
if(xhr.readyState === 3){
if(reply && 0 < reply.length){
opt.ondata(status, reply);
}
} else
if(xhr.readyState === 4){
opt.ondata(status, reply, true);
clean(status === 200? 'network' : 'permanent');
}
ws.onmessage = function(m){
if(!m || !m.data){ return }
var res;
try{res = JSON.parse(m.data);
}catch(e){ return }
if(!res){ return }
if(res.wsrid){ (r.ws.cbs[res.wsrid]||function(){})(null, res) }
console.log("We have a pushed message!", res);
if(res.body){ r.createServer(res, function(){}) } // emit extra events.
};
opt.ondata = opt.ondata || function(status, chunk, end){
if(status !== 200){ return }
try{ajax.each(opt.header, function(val, i){
(xhr.responseHeader = xhr.responseHeader||{})[i.toLowerCase()] = xhr.getResponseHeader(i);
});
}catch(e){}
var data, buf, pos = 1;
while(pos || end){ // in order to end
if(u !== data){ // we need at least one loop
opt.onload({
headers: xhr.responseHeader || {}
,body: data
});
end = false; // now both pos and end will be false
ws.onerror = function(e){ console.log(e); };
return true;
}
if(ajax.string(chunk)){
buf = chunk.slice(xhr.index = xhr.index || 0);
pos = buf.indexOf('\n') + 1;
data = pos? buf.slice(0, pos - 1) : buf;
xhr.index += pos;
} else {
data = chunk;
pos = 0;
}
}
}
opt.onload = opt.onload || function(reply){
if(!reply){ return }
if( reply.headers && ("application/json" === reply.headers["content-type"])){
var body;
try{body = JSON.parse(reply.body);
}catch(e){body = reply.body}
reply.body = body;
}
if(cb){
r.ws.peers = {};
r.ws.cbs = {};
r.jsonp = function(opt, cb){
//console.log("jsonp send", opt);
r.jsonp.ify(opt, function(url){
//console.log(url);
if(!url){ return }
r.jsonp.send(url, function(reply){
//console.log("jsonp reply", reply);
cb(null, reply);
}
}
if(opt.cookies || opt.credentials || opt.withCredentials){
xhr.withCredentials = true;
}
opt.headers["X-Requested-With"] = xhr.transport || "XMLHttpRequest";
try{xhr.open(opt.method, url, true);
}catch(e){ return xhr.onerror("Open failed.") }
if(opt.headers){
try{ajax.each(opt.headers, function(val, i){
xhr.setRequestHeader(i, val);
r.jsonp.poll(opt, reply);
}, opt.jsonp);
});
}catch(e){ return xhr.onerror("Invalid headers.") }
}
try{xhr.send(data);
}catch(e){ return xhr.onerror("Failed to send request.") }
}
ajax.xhr = function(xhr){
return (window.XMLHttpRequest && "withCredentials" in (xhr = new XMLHttpRequest()))? xhr : null;
}
ajax.jsonp = function(xhr){
xhr = {};
xhr.transport = "jsonp";
xhr.open = function(method, url){
xhr.url = url;
}
xhr.send = function(){
xhr.url += ((xhr.url.indexOf('?') + 1)? '&' : '?') + 'jsonp=' + xhr.js.id;
ajax.each(xhr.headers, function(val, i){
xhr.url += '&' + encodeURIComponent(i) + "=" + encodeURIComponent(val);
});
xhr.js.src = xhr.url = xhr.url.replace(/%20/g, "+");
document.getElementsByTagName('head')[0].appendChild(xhr.js);
}
xhr.setRequestHeader = function(i, val){
(xhr.headers = xhr.headers||{})[i] = val;
}
xhr.getResponseHeader = function(i){ return (xhr.responseHeaders||{})[i] }
xhr.js = document.createElement('script');
window[xhr.js.id = 'P'+Math.floor((Math.random()*65535)+1)] = function(reply){
xhr.status = 200;
if(reply.chunks && reply.chunks.length){
xhr.readyState = 3
while(0 < reply.chunks.length){
xhr.responseText = reply.chunks.shift();
xhr.onreadystatechange();
}
}
xhr.responseHeaders = reply.headers || {};
xhr.readyState = 4;
xhr.responseText = reply.body;
xhr.onreadystatechange();
xhr.id = xhr.js.id;
xhr.js.parentNode.removeChild(xhr.js);
window[xhr.id] = null;
try{delete window[xhr.id];
r.jsonp.send = function(url, cb, id){
var js = document.createElement('script');
js.src = url;
window[js.id = id] = function(res){
cb(res);
cb.id = js.id;
js.parentNode.removeChild(js);
window[cb.id] = null; // TODO! BUG: This needs to handle chunking!
try{delete window[cb.id];
}catch(e){}
}
xhr.abort = function(){} // clean up?
xhr.js.async = true;
return xhr;
js.async = true;
document.getElementsByTagName('head')[0].appendChild(js);
return js;
}
ajax.string = function(s){ return (typeof s == 'string') }
ajax.each = function(obj, cb){
r.jsonp.poll = function(opt, res){
if(!opt || !opt.base || !res || !res.headers || !res.headers.poll){ return }
(r.jsonp.poll.s = r.jsonp.poll.s || {})[opt.base] = r.jsonp.poll.s[opt.base] || setTimeout(function(){ // TODO: Need to optimize for Chrome's 6 req limit?
//console.log("polling again");
var o = {base: opt.base, headers: {pull: 1}};
r.each(opt.headers, function(v,i){ o.headers[i] = v })
r.jsonp(o, function(err, reply){
delete r.jsonp.poll.s[opt.base];
//console.log(' ');
while(reply.body && reply.body.length && reply.body.shift){ // we're assuming an array rather than chunk encoding. :(
var res = reply.body.shift();
//console.log("-- go go go", res);
if(res && res.body){ r.createServer(res, function(){}) } // emit extra events.
}
});
}, res.headers.poll);
}
r.jsonp.ify = function(opt, cb){
var uri = encodeURIComponent, q = '?';
if(opt.url && opt.url.pathname){ q = opt.url.pathname + q; }
q = opt.base + q;
//console.log("what up doc?", opt);
r.each((opt.url||{}).query, function(v, i){ q += uri(i) + '=' + uri(v) + '&' });
if(opt.headers){ q += uri('`') + '=' + uri(JSON.stringify(opt.headers)) + '&' }
if(r.jsonp.max < q.length){ return cb() }
q += uri('jsonp') + '=' + uri(opt.jsonp = 'P'+Math.floor((Math.random()*65535)+1));
if(opt.body){
q += '&';
var w = opt.body, wls = function(w,l,s){
return uri('%') + '=' + uri(w+'-'+(l||w)+'/'+(s||w)) + '&' + uri('$') + '=';
}
if(typeof w != 'string'){
w = JSON.stringify(w);
q += uri('^') + '=' + uri('json') + '&';
}
w = uri(w);
var i = 0, l = w.length
, s = r.jsonp.max - (q.length + wls(l.toString()).length);
if(s < 0){ return cb() }
while(w){
cb(q + wls(i, (i = i + s), l) + w.slice(0, i));
w = w.slice(i);
}
} else {
cb(q);
}
}
r.jsonp.max = 2000;
r.each = function(obj, cb){
if(!obj || !cb){ return }
for(var i in obj){
if(obj.hasOwnProperty(i)){
@ -1054,9 +1075,6 @@
}
}
}
return ajax;
return r;
}());
gun.__.opt.hooks.load = gun.__.opt.hooks.load || tab.load;
gun.__.opt.hooks.set = gun.__.opt.hooks.set || tab.set;
});
}({}));

577
gun0.js
View File

@ -1,577 +0,0 @@
/**** The Abstact Structure
A JSON graph structure that is lightweight and flexible to describe anything.
The current goal, however, is limited to encompassing HTML and CSS for starters.
Immediately after that is describing code as a state.
A node is something which has relationships and or value.
Relationships and values aren't any different, other than that
a relationship is a reference and a value is embedded.
*****/
module.exports = require('theory')
('gun',function(a){
a.gun = (function(){
function gun(p,v,w){
var args = arguments.length
, cb = a.fns.is(v)? v : null
, g, n, b, w = w || a.time.now();
if(gun.is(this)){
n = this;
g = n._.clip || function(){ return {} };
if(a.text.is(p)){
if(args >= 2){ // set
var u, ref = {}
, val = gun.at(n,p,ref);
if(!ref.cartridge || !ref.cartridge._ || !ref.cartridge._[gun._.id]){
return;
} ref.id = ref.cartridge._[gun._.id] +'.'+ ref.path;
v = gun.ify.be(v);
b = gun.bullet(ref.path,v,w);
console.log("after:", v, b);
if(a.gun.ham){
v = a.gun.ham(ref.cartridge,b,v,w); // TODO: BUG! Need to update when also!
if(v === u){
console.log("HAM REJECTION", p, v, val);
return;
}
}
console.log("HAM set", p, v);
if(ref.at){
if(v === null){
if(a.list.is(ref.at)){
t = o.val || t;
var j = ref.at.indexOf(ref.prop);
if(0 <= j){
ref.at.splice(j,1);
} else {
j = a.list(ref.at).find(gun.id(ref.prop));
if(j){
ref.at.splice(--j,1);
}
}
} else {
delete ref.at[ref.prop];
}
var del = {}; del[ref.id] = null;
gun.fire(del, g[gun._.id], w);
v = ref.at;
} else {
if(a.fns.is(v) && v[gun._.id]){ // then it is a clip!
v = {};
}
v = gun.at(v);
if(gun.is(v)){
v = gun.id(v._[gun._.id]); // update this to handle clip#cart
} else {
v = gun.ify.be(v);
}
if(a.obj.is(v)){
ref.at[ref.prop] = v;
//ref.tmp = ref.at[ref.prop] = gun.ify.obj(v, val);
} else
if(a.list.is(v)){
ref.tmp = ref.at[ref.prop] = gun.ify.list(v, val);
} else {
ref.at[ref.prop] = v;
}
var diff = {}; diff[ref.id] = v;
gun.fire(diff, g[gun._.id], w);
v = ref.tmp || v;
}
return v;
}
return;
}
if(args >= 1){ // get
v = gun.at(n,p);
return v;
}
}
return;
}
n = a.obj.is(v)? v : a.obj.is(p)? p : null;
p = a.text.is(p)? p : gun.id();
if(a.obj.is(n)){ // create a clip from this object
var c;
g = gun.ify(n);
if((c = gun.magazine[p]) && a.fns.is(c)){
console.log("clip already exists in magazine,", p);
a.obj(g).each(function(n,id){
if(!gun.is(n)){ return }
c(id,n);
});
return gun.magazine[p];
}
var clip = gun.magazine[p] = function(p,v,w){
var args, id, path, n, w = w || a.time.now();
if(a.text.is(p)){
id = a.text(p).clip('.',0,1);
path = a.text(p).clip('.',1);
if(a.obj(g).has(id) && gun.is(g[id])){
n = g[id];
p = path;
}
}
args = a.list.slit.call(arguments);
if(!args.length){
return g;
}
if(path){
if(n){
n._.clip = n._.clip || clip;
return gun.apply(n, args);
}
return;
}
var fn = function(p,v,w){
if(!n){ return }
var args = a.list.slit.call(arguments);
return !args.length? n : gun.apply(n,args);
}
if(n){
if(args.length === 1){
n._.clip = n._.clip || clip;
return fn;
}
if(gun.is(v) && gun.ham){
var h = v._[gun._.ham] || {};
a.obj(v).each(function(v,p){
if(p === '_'){ return }
console.log('-------------->', p, h[p], h, 1); // Wait! This isn't correct because it should be '>' not '.'!
fn(p, v, h[p] || (a.num.is(h)? h : 1)); // Wait! This isn't correct because it should be '>' not '.'!
});
return fn;
}
if(v === null){
delete g[n._[gun._.id]];
var del = {}; del[n._[gun._.id]] = n = null;
gun.fire(del, g[gun._.id], w); // TODO: BUG! HAM UPDATES!
return null;
}
return;
}
if(a.text.is(p) && a.obj.is(v)){
v = v;
v._ = gun.id(p);
} else
if(a.obj.is(p)){
v = p;
}
if(a.obj.is(v)){
n = gun.ify(v,u,{}); // a clip cannot be created from this, only a single cartridge
n._ = n._ || gun.id({});
n._.clip = clip; // JSONifying excludes functions.
var add = {}; add[n._[gun._.id]] = g[n._[gun._.id]] = n;
gun.fire(add, clip[gun._.id], w); // TODO: BUG! HAM UPDATES!
return fn;
}
}
clip[gun._.id] = p;
return clip;
}
} var u;
gun._ = {
id: '#' // do not change this!
}
gun.is = function(o){
return (o && o._ && o._[gun._.id])? true : false;
}
gun.id = function(t){
if(t){
var _ = {};_[gun._.id] = a.text.is(t)? t : gun.id();
return _;
}
return a.text.r(9);
}
gun.at = function(n,p,ref){
if(a.fns.is(n)){
n = n();
}
if(!p){
return n;
}
ref = ref || {};
var pp = a.list.is(p)? p : (p||'').split('.')
, g = a.fns.is(n._.clip)? n._.clip() : this
, i = 0, l = pp.length, v = n
, x, y, z;
ref.cartridge = n;
ref.prop = pp[l-1];
ref.path = pp.slice(i).join('.');
while(i < l && v !== u){
x = pp[i++];
if(a.obj.is(v) && a.obj(v).has(x)){
ref.at = v;
v = v[x];
if(v && v[gun._.id]){
v = a.obj(g).has(v[gun._.id])? g[v[gun._.id]] : u;
if(v){
return gun.at.call(g,v,pp.slice(i),ref);
}
}
} else
if(a.list.is(v)){
ref.at = v;
return a.list(v).each(function(w,j){
if(!w) return;
if(!p) return;
w = a.obj(g).has(w[gun._.id]||w)? g[w[gun._.id]||w] : u;
if(!w) return;
if(w._ && x === w._[gun._.id]){
i += 1;
p = false;
}
return gun.at.call(g,w,pp.slice(i-1),ref);
});
} else {
ref.at = v;
v = u;
}
}
if(a.list.is(v)){
ref.at = v;
v = a.list(v).each(function(w,j,t){
if(w){
if(a.obj(g).has(w[gun._.id]||w)) t(g[w[gun._.id]||w]);
}
}) || [];
}
return i < l? u : v;
}
gun.ify = function(o, opt, n){
var g = {};
opt = opt || {};
opt.seen = opt.seen || [];
if(!a.obj.is(o)){ return g }
function ify(o,i,f,n,p){
if(gun.ify.is(o)){
f[i] = o;
return
}
if(a.obj.is(o)){
var seen;
if(seen = ify.seen(o)){
ify.be(seen);
return;
}
if(gun.is(o)){
f[i] = gun.id(o._[gun._.id]);
g[o._[gun._.id]] = n;
} else {
f[i] = n;
}
opt.seen.push({cartridge: n, prop: i, from: f, src: o});
a.obj(o).each(function(v,j){
ify(v,j,n,{},f);
});
if(gun.is(n)){
g[n._[gun._.id]] = n;
f[i] = gun.id(n._[gun._.id]);
}
return;
}
if(a.list.is(o)){
f[i] = a.list(o).each(function(v,j,t){
var seen;
if(a.fns.is(v)){
v = gun.at(v);
}
if(a.obj.is(v)){
if(seen = ify.seen(v)){
ify.be(seen);
if(gun.is(seen.cartridge)){ t(seen.cartridge._[gun._.id]) }
} else {
gun.ify(v, opt, n);
if(gun.is(n)){
t(n._[gun._.id]);
}
}
} else
if(a.text.is(v)){
if(a.obj(g).has(v)){
t(v);
} else {
t(v); // same as above :/ because it could be that this ID just hasn't been indexed yet.
}
}
}) || [];
return;
}
}
ify.be = function(seen){
var n = seen.cartridge;
n._ = n._||{};
n._[gun._.id] = n._[gun._.id]||gun.id();
g[n._[gun._.id]] = n;
if(seen.from){
seen.from[seen.prop] = gun.id(n._[gun._.id]);
}
}
ify.seen = function(o){
return a.list(opt.seen).each(function(v){
if(v && v.src === o){ return v }
}) || false;
}
var is = true, cartridge = n || {};
a.obj(o).each(function(v,i){
if(!gun.is(v)){ is = false }
ify(v, i, cartridge, {});
});
if(!is){
ify.be({cartridge: cartridge});
g[cartridge._[gun._.id]] = cartridge;
}
if(n){
return n;
}
return g;
}
gun.ify.be = function(v,g){ // update this to handle externals!
var r;
g = g || {};
if(gun.ify.is(v)){
r = v;
} else
if(a.obj.is(v)){
r = {};
a.obj(v).each(function(w,i){
w = gun.ify.be(w);
if(w === u){ return }
r[i] = w;
});
} else
if(a.list.is(v)){ // references only
r = a.list(v).each(function(w,i,t){
if(!w){ return }
w = gun.at(w);
if(gun.is(w)){
t(w._[gun._.id]);
} else
if(w[gun._.id]){
t(w[gun._.id]);
} else
if(a.obj(g).has(w)){
t(w);
}
}) || [];
}
return r;
}
gun.ify.is = function(v){ // null, binary, number (!Infinity), text, or a ref.
if(v === null){ return true } // deletes
if(v === Infinity){ return false }
if(a.bi.is(v)
|| a.num.is(v)
|| a.text.is(v)){
return true; // simple values
}
if(a.obj.is(v) && a.text.is(v[gun._.id])){ // ref
return true;
}
return false;
}
gun.ify.obj = function(v, val){
if(a.obj.is(val) && a.obj.is(v)){
a.obj(v).each(function(d, i){
if(a.gun.ham && a.gun.ham.call(g,n,p,v,w,val)){
}
});
}
return v;
}
gun.ify.list = function(v, val){
var r;
r = a.list.is(val)? val.concat(v) : v;
r = a.list(r).each(function(r,i,t){t(r,1)})||{};
r = a.obj(r).each(function(w,r,t){t(r)})||[]; // idempotency of this over latency? TODO! INVESTIGATE!!
return r;
}
gun.duel = function(old,now){
a.obj(now).each(function(g,id){
if(!gun.is(g)){ return }
var c;
if(a.obj(old).has(id) && gun.is(c = old[id])){
a.obj(g).each(function(v,i){
});
} else {
old[id] = g;
}
});
}
gun.bullet = function(p,v,w){
var b = {};
b[p] = v;
if(gun.ham && gun._.ham){
b._ = {};
b._[gun._.ham] = w || a.time.now();
}
return b;
}
gun.fire = function(bullet,c,w,op){
bullet = bullet.what? bullet : {what: bullet};
bullet.where = c || bullet.where;
bullet.when = w || bullet.when;
if(!a.obj.is(bullet.what)){ return gun.fire.jam("No ammo.", bullet) }
if(!a.num.is(bullet.when)){ return gun.fire.jam("No time.", bullet) }
if(!a.text.is(bullet.where)){ return gun.fire.jam("No location.", bullet) }
bullet.how = bullet.how || {};
bullet.how.gun = op || 1;
theory.on(gun.event).emit(bullet);
}
gun.fire.jam = function(s,b){ if(b){ return console.log("Gun jam:",s,b) } console.log("Gun jam:",s) }
gun.shots = function(hear,s){ return theory.on(gun.event+(s?'.'+s:'')).event(hear) }
gun.event = 'gun';
gun.magazine = {};
return gun;
})();
/* Hypothetical Amnesia Machine
A thought experiment in efficient cause, linear time, and knowledge.
Suppose everything you will ever know in your life was already be stored
in your brain. Now suppose we have some machine, which delicately traverses
your mind and gives you amnesia about all these facts. You now no longer can
recall any of this knowledge because that information is disconnected from
all other pieces of knowledge - making it impossible for your mind to then
associate and thus remember things. But the curious fact is that all this
knowledge is still stored within your mind, it is just inaccessible.
Now suppose, this amnesia machine is designed to unlock various bits of
that knowledge, making it connected again to other related tidbits and thus
making it accessible to you. This unlocking process is activated at some pre-
determined value, such as a timestamp. Can it really be said that this is
indistinguishable from the supposed flow of past, present, and future?
Such that future information is not just unknown, but fundamentally does
not exist, and then by actions taken in the present is caused to be. As a
result of your senses, you then experience this effect, and thus 'learning'
that knowledge. Could we truly build a proof that reality is one way or the
other? But if we did, wouldn't that scurrying little machine just race across
our minds and assure it induces amnesia into our remembrance of its existence?
Nay, we cannot. We can only hypothesize about the existence of this crafty
device. For the blindness that it does shed upon us captivates our perception
of how the world really is, us forever duped into thinking time is linear.
And here, in write and code, is this machine used and exploited. Holding
in its power the ability to quarantine and keep secret, until upon some
value, some condition, some scheme or rendition, does it raise its mighty
clutch of deception and expose the truth, shining in its radiance and glory,
all at the ease of making a single connection. Whereupon we do assure that
all conscious actors are agreed upon in a unified spot, synchronized in the
capacity to realize such beautiful information.
*/
a.gun._.ham = '>';
a.gun.ham = function(n,p,v,w){
if(!n){ return }
console.log("HAM:", n, p, v, w);
if(!a.text.is(p)){
if(a.obj.is(p) && p._){
a.obj(p).each(function(sv,i){
if(i === '_'){ return }
v = sv = a.gun.ham(n,i,sv, a.gun.ham.when(p._, i) || w); // works for now, but may not on other non-bullet objects
if(sv === u){
delete p[i];
} else {
p[i] = sv;
}
});
return v;
}
return;
}
var val = a.gun.at(n,p)
, when, age, now, u, q;
q = p.replace('.',a.gun._.ham);
n._ = n._ || {};
n._[a.gun._.ham] = n._[a.gun._.ham] || {};
age = function(q){
if(!q){ return 0 }
var when = n._[a.gun._.ham][q];
if(when || when === 0){
return when;
}
return age(a.text(q).clip(a.gun._.ham,0,-1));
}
when = age(q);
v = (function(){
if(a.gun.ify.is(v)){ // simple values are directly resolved
return v;
} else
if(a.obj.is(v)){
if(a.obj.is(val)){ // resolve sub-values
var change = false;
a.obj(v).each(function(sv,i){
sv = a.gun.ham(n, (p+'.'+i), sv, w, val[i]); // TODO: BUG! Still need to deal with sub-value bullets resolving to container's age.
if(sv === u){ return }
change = true;
val[i] = sv;
});
if(change){
return v = val;
} else {
return;; // nothing new
}
}
a.obj(v).each(function(sv,i){
sv = a.gun.ham(n, (p+'.'+i), sv, w, (val||{})[i]);
if(sv === u){ delete v[i] }
});
return v;
} else
if(a.list.is(v)){
if(!a.list.is(val)){ // TODO: deal with this later.
return v;
}
return v;
} else { // unknown matches are directly resolved
return;
}
})();
if(v === u){ return }
if(w < when){
console.log("new < old");
return;
} else
if(w === when){ // this needs to be updated also!
if(val === v || a.test.is(val,v) || a.text.ify(val) < a.text.ify(v)){
console.log("new === old");
return;
}
} else
if((now = a.time.now() + 1) < w){ // tolerate a threshold of 1ms.
console.log("amnesia", Math.ceil(w - now));
/* Amnesia Quarantine */
a.time.wait(function(){
console.log("run again");
a.gun.call(n,p,v,w);
}, Math.ceil(w - now)); // crude implementation for now.
return;
}
v = (function(){
if(a.obj.is(v)){
w = when; // objects are resolved relative to their previous values.
}
return v;
})();
n._[a.gun._.ham][q] = w; // if properties get deleted it may be nice to eventually delete the HAM, but that could cause problems so we don't for now.
// ps. It may be possible to delete simple values if they are not proceeded by an object?
return v;
}
a.gun.ham.when = function(w, i){
var h;
if(w && w._){
w = w._;
}
if(w && (h = w[a.gun._.ham])){
if(a.obj(h).has(i)){
return h[i];
}
if(a.num.is(h)){
return h;
}
}
}
return a.gun;
});

View File

@ -1,17 +0,0 @@
var Gun = require('gun');
var gun = Gun({
s3: {
key: '', // AWS Access Key
secret: '', // AWS Secret Token
bucket: '' // The bucket you want to save into
}});
gun.set({ hello: 'world' }).key('my/first/data')
var http = require('http');
http.createServer(function (req, res) {
gun.load('my/first/data', function(data){
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(data));
});
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

View File

@ -4,7 +4,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
<style>
body {
background-image: url(./img/kimber.jpg);
background-image: url(./web/img/kimber.jpg);
background-repeat: no-repeat;
background-position: left top;
font-family: Arial;

View File

@ -1 +1 @@
module.exports = require('./shots');
module.exports = require('./lib/server');

31
init.js
View File

@ -1,31 +0,0 @@
(function(){
process.env.rootdir = __dirname;
var LIVE = process.env.LIVE || (process.env.NODE_ENV === 'production'), web, opt = {};
opt.port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT;
opt.host = process.env.OPENSHIFT_NODEJS_IP;
if(opt.port || opt.host){ LIVE = true }
opt.port = opt.port || 8888;
opt.host = opt.host || '0.0.0.0';
if(LIVE){
//process.env['redis-install'] = '/tmp';
} else {
// Keys are hosted outside this folder, you must provide your own with environment variables.
var keys = '../../linux/.ssh/keys-gun.js';
if((require('fs').existsSync||require('path').existsSync)(keys)){
require(keys);
}
if((require('fs').existsSync||require('path').existsSync)('../coalesce')){
web = require('../coalesce');
}
}
opt.run = ['./test/server', './test/tests', './test/shoot'];
opt.node = {key: "temp gun key", src:["http://gunjs.herokuapp.com/com","http://gunjs-amark.rhcloud.com/com","http://gunjs.aws.af.cm/com"]};
web = web || require('coalesce');
web(opt);
console.log("Gun @ "+ opt.port);
})();

View File

@ -127,7 +127,7 @@
return this;
}
return s3;
})(require('../gun'), {});
})(require('gun/gun'), {});
/**
Knox S3 Config is:
knox.createClient({

50
lib/http.js Normal file
View File

@ -0,0 +1,50 @@
var Gun = require('gun/gun')
, formidable = require('formidable')
, url = require('url');
module.exports = function(req, res, next){
next = next || function(){};
if(!req || !res){ return next() }
if(!req.url){ return next() }
if(!req.method){ return next() }
var msg = {};
msg.url = url.parse(req.url, true);
msg.method = (req.method||'').toLowerCase();
msg.headers = req.headers;
var u, body
, form = new formidable.IncomingForm()
, post = function(err, body){
if(u !== body){ msg.body = body }
next(msg, function(reply){
if(!res){ return }
if(!reply){ return res.end() }
if(Gun.obj.has(reply, 'statusCode') || Gun.obj.has(reply, 'status')){
res.statusCode = reply.statusCode || reply.status;
}
if(reply.headers){
if(!res._headerSent){
Gun.obj.map(reply.headers, function(val, field){
res.setHeader(field, val);
});
}
}
if(Gun.obj.has(reply,'chunk') || Gun.obj.has(reply,'write')){
res.write(Gun.text.ify(reply.chunk || reply.write) || '');
}
if(Gun.obj.has(reply,'body') || Gun.obj.has(reply,'end')){
res.end(Gun.text.ify(reply.body || reply.end) || '');
}
});
}
form.on('field',function(k,v){
(body = body || {})[k] = v;
}).on('file',function(k,v){
return; // files not supported in gun yet
}).on('error',function(e){
if(form.done){ return }
post(e);
}).on('end', function(){
if(form.done){ return }
post(null, body);
});
form.parse(req);
}

37
lib/jsonp.js Normal file
View File

@ -0,0 +1,37 @@
var Gun = require('gun/gun');
module.exports = function(req, cb){
if(!req.url || !req.url.query || !req.url.query.jsonp){ return cb }
cb.jsonp = req.url.query.jsonp;
delete req.url.query.jsonp;
Gun.obj.map(Gun.obj.ify(req.url.query['`']), function(val, i){
req.headers[i] = val;
});
delete req.url.query['`'];
if(req.url.query.$){
req.body = req.url.query.$;
if(!Gun.obj.has(req.url.query, '^') || 'json' == req.url.query['^']){
req.body = Gun.obj.ify(req.body); // TODO: BUG! THIS IS WRONG! This doesn't handle multipart chunking, and will fail!
}
}
delete req.url.query.$;
delete req.url.query['^'];
delete req.url.query['%'];
var reply = {headers:{}};
return function(res){
if(!res){ return }
if(res.headers){
Gun.obj.map(res.headers, function(val, field){
reply.headers[field] = val;
});
}
reply.headers['Content-Type'] = "text/javascript";
if(Gun.obj.has(res,'chunk') && (!reply.body || Gun.list.is(reply.chunks))){
(reply.chunks = reply.chunks || []).push(res.chunk);
}
if(Gun.obj.has(res,'body')){
reply.body = res.body; // self-reference yourself so on the client we can get the headers and body.
reply.body = ';'+ cb.jsonp + '(' + Gun.text.ify(reply) + ');'; // javascriptify it! can't believe the client trusts us.
cb(reply);
}
}
}

113
lib/s3.js Normal file
View File

@ -0,0 +1,113 @@
;(function(){
var Gun = require('gun/gun');
var S3 = require('./aws');
Gun.on('opt').event(function(gun, opt){
opt.s3 = opt.s3 || {};
var s3 = gun.__.opt.s3 = gun.__.opt.s3 || S3(opt && opt.s3);
s3.prefix = s3.prefix || opt.s3.prefix || '';
s3.prekey = s3.prekey || opt.s3.prekey || '';
s3.prenode = s3.prenode || opt.s3.prenode || '_/nodes/';
gun.__.opt.batch = opt.batch || gun.__.opt.batch || 10;
gun.__.opt.throttle = opt.throttle || gun.__.opt.throttle || 15;
gun.__.opt.disconnect = opt.disconnect || gun.__.opt.disconnect || 5;
s3.load = s3.load || function(key, cb, opt){
if(!key){ return }
cb = cb || function(){};
opt = opt || {};
if(key[Gun._.soul]){
key = s3.prefix + s3.prenode + key[Gun._.soul];
} else {
key = s3.prefix + s3.prekey + key;
}
s3.get(key, function(err, data, text, meta){
console.log('via s3', key, err);
if(meta && meta[Gun._.soul]){
return s3.load(meta, cb);
}
if(err && err.statusCode == 404){
err = null; // we want a difference between 'unfound' (data is null) and 'error' (auth is wrong).
}
cb(err, data);
});
}
s3.set = s3.set || function(nodes, cb){
s3.batching += 1;
cb = cb || function(){};
cb.count = 0;
var next = s3.next
, ack = Gun.text.random(8)
, batch = s3.batch[next] = s3.batch[next] || {};
s3.on(ack).once(cb);
Gun.obj.map(nodes, function(node, soul){
cb.count += 1;
batch[soul] = (batch[soul] || 0) + 1;
//console.log("set listener for", next + ':' + soul, batch[soul], cb.count);
s3.on(next + ':' + soul).event(function(){
cb.count -= 1;
//console.log("transaction", cb.count);
if(!cb.count){
s3.on(ack).emit();
this.off(); // MEMORY LEAKS EVERYWHERE!!!!!!!!!!!!!!!! FIX THIS!!!!!!!!!
}
});
});
if(gun.__.opt.batch < s3.batching){
return s3.set.now();
}
if(!gun.__.opt.throttle){
return s3.set.now();
}
s3.wait = s3.wait || setTimeout(s3.set.now, gun.__.opt.throttle * 1000); // in seconds
}
s3.set.now = s3.set.now || function(){
clearTimeout(s3.wait);
s3.batching = 0;
s3.wait = null;
var now = s3.next
, batch = s3.batch[s3.next];
s3.next = Gun.time.is();
Gun.obj.map(batch, function put(exists, soul){
var node = gun.__.graph[soul]; // the batch does not actually have the nodes, but what happens when we do cold data? Could this be gone?
s3.put(s3.prefix + s3.prenode + soul, node, function(err, reply){
console.log("s3 put reply", soul, err, reply);
if(err || !reply){
put(exists, soul); // naive implementation of retry TODO: BUG: need backoff and anti-infinite-loop!
return;
}
s3.on(now + ':' + soul).emit(200);
});
});
}
s3.next = s3.next || Gun.time.is();
s3.on = s3.on || Gun.on.create();
s3.batching = s3.batching || 0;
s3.batched = s3.batched || {};
s3.batch = s3.batch || {};
s3.persisted = s3.persisted || {};
s3.wait = s3.wait || null;
s3.key = s3.key || function(key, soul, cb){
var meta = {};
meta[Gun._.soul] = soul = Gun.text.is(soul)? soul : (soul||{})[Gun._.soul];
if(!soul){
return cb({err: "No soul!"});
}
s3.put(s3.prefix + s3.prekey + key, '', function(err, reply){ // key is 2 bytes??? Should be smaller. Wait HUH? What did I mean by this?
console.log("s3 put reply", soul, err, reply);
if(err || !reply){
s3.key(key, soul, cb); // naive implementation of retry TODO: BUG: need backoff and anti-infinite-loop!
return;
}
cb();
}, {Metadata: meta});
}
opt.hooks = opt.hooks || {};
gun.opt({hooks: {
load: opt.hooks.load || s3.load
,set: opt.hooks.set || s3.set
,key: opt.hooks.key || s3.key
}}, true);
});
}());

7
lib/server.js Normal file
View File

@ -0,0 +1,7 @@
;(function(){
console.log("Hello wonderful person! :) I'm mark@gunDB.io, message me for help or with hatemail. I want to hear from you! <3");
var Gun = require('../gun');
require('./s3');
require('./wsp');
module.exports = Gun;
}());

37
lib/ws.js Normal file
View File

@ -0,0 +1,37 @@
var Gun = require('gun/gun')
, url = require('url');
module.exports = function(wss, server){
wss.on('connection', function(ws){
var req = {};
ws.upgradeReq = ws.upgradeReq || {};
req.url = url.parse(ws.upgradeReq.url||'');
req.method = (ws.upgradeReq.method||'').toLowerCase();
req.headers = ws.upgradeReq.headers || {};
//console.log("wsReq", req);
ws.on('message', function(msg){
msg = Gun.obj.ify(msg);
msg.url = msg.url || {};
msg.url.pathname = (req.url.pathname||'') + (msg.url.pathname||'');
Gun.obj.map(req.url, function(val, i){
msg.url[i] = msg.url[i] || val; // reattach url
});
msg.method = msg.method || req.method;
msg.headers = msg.headers || {};
Gun.obj.map(req.headers, function(val, i){
msg.headers[i] = msg.headers[i] || val; // reattach headers
});
server.call(ws, msg, function(reply){
if(!ws || !ws.send){ return }
reply = reply || {};
reply.wsrid = msg.wsrid;
ws.send(Gun.text.ify(reply));
});
});
ws.off = function(m){
console.log("ws.off", m);
ws.send = null;
}
ws.on('close', ws.off);
ws.on('error', ws.off);
});
}

153
lib/wsp.js Normal file
View File

@ -0,0 +1,153 @@
;(function(wsp){
var Gun = require('gun/gun')
, formidable = require('formidable')
, ws = require('ws').Server
, http = require('./http')
, url = require('url');
Gun.on('opt').event(function(gun, opt){
gun.__.opt.ws = opt.ws = gun.__.opt.ws || opt.ws || {};
gun.attach = gun.attach || function(app){
if(app.use){
app.use(gun.server);
}
var listen = app.listen;
app.listen = function(port){
var server = listen.apply(app, arguments);
gun.__.opt.ws.server = gun.__.opt.ws.server || opt.ws.server || server;
gun.__.opt.ws.path = gun.__.opt.ws.path || opt.ws.path || '/gun';
require('./ws')(gun.server.websocket = gun.server.websocket || new ws(gun.__.opt.ws), function(req, res){
var ws = this;
req.headers['gun-tid'] = ws.tid = ws.tid? ws.tid : req.headers['gun-tid'];
ws.sub = ws.sub || gun.server.on('network').event(function(msg){
if(!ws || !ws.send){ return this.off() }
if(!msg || (msg.headers && msg.headers['gun-tid'] === ws.tid)){ return }
delete msg.wsrid; // depreciate this!
ws.send(Gun.text.ify(msg));
});
gun.__.opt.hooks.transport(req, res);
});
gun.__.opt.ws.port = port || opt.ws.port || gun.__.opt.ws.port || 80;
return server;
}
return gun;
}
gun.server = gun.server || function(req, res, next){
//console.log("\n\n GUN SERVER!", req);
next = next || function(){};
if(!req || !res){ return next() }
if(!req.url){ return next() }
if(!req.method){ return next() }
var msg = {};
msg.url = url.parse(req.url, true);
if(!gun.server.regex.test(msg.url.pathname)){ return next() }
if(msg.url.pathname.replace(gun.server.regex,'').slice(0,3).toLowerCase() === '.js'){
res.writeHead(200, {'Content-Type': 'text/javascript'});
res.end(gun.server.js = gun.server.js || require('fs').readFileSync(__dirname + '/../gun.js')); // gun server is caching the gun library for the client
return;
}
http(req, res, function(req, res){
if(!req){ return next() }
var tab, cb = res = require('./jsonp')(req, res);
if(req.headers && (tab = req.headers['gun-tid'])){
tab = (gun.server.peers = gun.server.peers || {})[tab] = gun.server.peers[tab] || {tid: tab};
tab.sub = tab.sub || gun.server.on('network').event(function(req){
if(!tab){ return this.off() } // self cleans up after itself!
if(!req || (req.headers && req.headers['gun-tid'] === tab.tid)){ return }
(tab.queue = tab.queue || []).push(req);
tab.drain(tab.reply);
});
cb = function(r){ (r.headers||{}).poll = gun.__.opt.poll; res(r) }
tab.drain = tab.drain || function(res){
if(!res || !tab || !tab.queue || !tab.queue.length){ return }
res({headers: {'gun-tid': tab.tid}, body: tab.queue });
tab.off = setTimeout(function(){ tab = null }, gun.__.opt.pull);
tab.reply = tab.queue = null;
return true;
}
clearTimeout(tab.off);
if(req.headers.pull){
if(tab.drain(cb)){ return }
return tab.reply = cb;
}
}
gun.__.opt.hooks.transport(req, cb);
});
}
gun.server.on = gun.server.on || Gun.on.create();
gun.__.opt.poll = gun.__.opt.poll || opt.poll || 1;
gun.__.opt.pull = gun.__.opt.pull || opt.pull || gun.__.opt.poll * 1000;
gun.server.regex = gun.__.opt.route = gun.__.opt.route || opt.route || /^\/gun/i;
if((gun.__.opt.maxSockets = opt.maxSockets || gun.__.opt.maxSockets) !== false){
require('https').globalAgent.maxSockets = require('http').globalAgent.maxSockets = gun.__.opt.maxSockets || Infinity; // WARNING: Document this!
}
/* gun.server.xff = function(r){
if(!r){ return '' }
var req = {headers: r.headers || {}, connection: r.connection || {}, socket: r.socket || {}};
return req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || (req.connection.socket || {}).remoteAddress || '';
} */
gun.server.transport = gun.server.transport || (function(){
// all streams, technically PATCH but implemented as POST, are forwarded to other trusted peers
// except for the ones that are listed in the message as having already been sending to.
// all states, implemented with GET, are replied to the source that asked for it.
function tran(req, cb){
//console.log("gun.server", req);
req.method = req.body? 'post' : 'get'; // post or get is based on whether there is a body or not
req.url.key = req.url.pathname.replace(gun.server.regex,'').replace(/^\//i,'') || '';
if('get' == req.method){ return tran.load(req, cb) }
if('post' == req.method){ return tran.post(req, cb) }
cb({body: {hello: 'world'}});
}
tran.load = function(req, cb){
var key = req.url.key
, reply = {headers: {'Content-Type': tran.json}};
if(!key){
if(!Gun.obj.has(req.url.query, Gun._.soul)){
return cb({headers: reply.headers, body: {err: "No key or soul to load."}});
}
key = {};
key[Gun._.soul] = req.url.query[Gun._.soul];
}
gun.load(key, function(err, node){
//tran.sub.scribe(req.tab, node._[Gun._.soul]);
cb({headers: reply.headers, body: (err? (err.err? err : {err: err || "Unknown error."}) : node || null)});
});
}
tran.post = function(req, cb){
// NOTE: It is highly recommended you do your own POSTs through your own API that then saves to gun manually.
// This will give you much more fine-grain control over security, transactions, and what not.
var reply = {headers: {'Content-Type': tran.json}};
if(!req.body){ return cb({headers: reply.headers, body: {err: "No body"}}) }
if(req.url.key && Gun.obj.has(req.body, Gun._.soul)){ // key hook!
console.log("TODO: BUG! IMPLEMENT KEY TRANSPORT HOOK!");
return;
}
// saving
Gun.obj.map(req.body, function(node, soul){
if(soul != Gun.is.soul.on(node)){ return this.end("No soul!") }
gun.load(node._, this.add(soul));
}, Gun.fns.sum(function(err){
if(err){ return cb({headers: reply.headers, body: {err: err}}) }
gun.union(req.body, function(err, context){
if(err || context.err || !context.nodes){ return cb({headers: reply.headers, body: {err: err || context.err || "Union failed." }}) }
if(!Gun.fns.is(gun.__.opt.hooks.set)){ return cb({headers: reply.headers, body: {err: "Persistence not supported." }}) }
gun.__.opt.hooks.set(context.nodes, function(err, data){ // since we've already manually done the union, we can now directly call the persistence layer.
if(err){ return cb({headers: reply.headers, body: {err: err || "Persistence failed." }}) }
cb({headers: reply.headers, body: {ok: "Persisted."}});
});
});
}));
gun.server.on('network').emit(req);
}
gun.server.on('network').event(function(req){
// TODO: MARK! You should move the networking events to here, not in WSS only.
});
tran.json = 'application/json';
return tran;
}());
opt.hooks = opt.hooks || {};
gun.opt({hooks: {
transport: opt.hooks.transport || gun.server.transport
}}, true);
});
}({}));

View File

@ -1,7 +1,5 @@
;(function(){
console.log("Hello wonderful person! :) I'm mark@gunDB.io, message me for help or with hatemail. I want to hear from you! <3");
var Gun = require(__dirname+'/gun')
, S3 = require(__dirname+'/gate/s3') // redis has been removed, can be replaced with a disk system
var Gun = require('gun/gun')
, formidable = require('formidable')
, url = require('url')
, meta = {};
@ -61,108 +59,8 @@
form.parse(req);
}
gun.server.regex = /^\/gun/i;
opt.s3 = opt.s3 || {};
var s3 = gun.__.opt.s3 = gun.__.opt.s3 || S3(opt && opt.s3);
s3.prefix = s3.prefix || opt.s3.prefix || '';
s3.prekey = s3.prekey || opt.s3.prekey || '';
s3.prenode = s3.prenode || opt.s3.prenode || '_/nodes/';
gun.__.opt.batch = opt.batch || gun.__.opt.batch || 10;
gun.__.opt.throttle = opt.throttle || gun.__.opt.throttle || 15;
gun.__.opt.disconnect = opt.disconnect || gun.__.opt.disconnect || 5;
if(!gun.__.opt.keepMaxSockets){ require('https').globalAgent.maxSockets = require('http').globalAgent.maxSockets = Infinity } // WARNING: Document this!
s3.load = s3.load || function(key, cb, opt){
if(!key){ return }
cb = cb || function(){};
opt = opt || {};
if(key[Gun._.soul]){
key = s3.prefix + s3.prenode + key[Gun._.soul];
} else {
key = s3.prefix + s3.prekey + key;
}
s3.get(key, function(err, data, text, meta){
console.log('via s3', key, err);
if(meta && meta[Gun._.soul]){
return s3.load(meta, cb);
}
if(err && err.statusCode == 404){
err = null; // we want a difference between 'unfound' (data is null) and 'error' (auth is wrong).
}
cb(err, data);
});
}
s3.set = s3.set || function(nodes, cb){
s3.batching += 1;
cb = cb || function(){};
cb.count = 0;
var next = s3.next
, ack = Gun.text.random(8)
, batch = s3.batch[next] = s3.batch[next] || {};
s3.on(ack).once(cb);
Gun.obj.map(nodes, function(node, soul){
cb.count += 1;
batch[soul] = (batch[soul] || 0) + 1;
//console.log("set listener for", next + ':' + soul, batch[soul], cb.count);
s3.on(next + ':' + soul).event(function(){
cb.count -= 1;
//console.log("transaction", cb.count);
if(!cb.count){
s3.on(ack).emit();
this.off(); // MEMORY LEAKS EVERYWHERE!!!!!!!!!!!!!!!! FIX THIS!!!!!!!!!
}
});
});
if(gun.__.opt.batch < s3.batching){
return s3.set.now();
}
if(!gun.__.opt.throttle){
return s3.set.now();
}
s3.wait = s3.wait || setTimeout(s3.set.now, gun.__.opt.throttle * 1000); // in seconds
}
s3.set.now = s3.set.now || function(){
clearTimeout(s3.wait);
s3.batching = 0;
s3.wait = null;
var now = s3.next
, batch = s3.batch[s3.next];
s3.next = Gun.time.is();
Gun.obj.map(batch, function put(exists, soul){
var node = gun.__.graph[soul]; // the batch does not actually have the nodes, but what happens when we do cold data? Could this be gone?
s3.put(s3.prefix + s3.prenode + soul, node, function(err, reply){
console.log("s3 put reply", soul, err, reply);
if(err || !reply){
put(exists, soul); // naive implementation of retry TODO: BUG: need backoff and anti-infinite-loop!
return;
}
s3.on(now + ':' + soul).emit(200);
});
});
}
s3.next = s3.next || Gun.time.is();
s3.on = s3.on || Gun.on.create();
s3.batching = s3.batching || 0;
s3.batched = s3.batched || {};
s3.batch = s3.batch || {};
s3.persisted = s3.persisted || {};
s3.wait = s3.wait || null;
s3.key = s3.key || function(key, soul, cb){
var meta = {};
meta[Gun._.soul] = soul = Gun.text.is(soul)? soul : (soul||{})[Gun._.soul];
if(!soul){
return cb({err: "No soul!"});
}
s3.put(s3.prefix + s3.prekey + key, '', function(err, reply){ // key is 2 bytes??? Should be smaller
console.log("s3 put reply", soul, err, reply);
if(err || !reply){
s3.key(key, soul, cb); // naive implementation of retry TODO: BUG: need backoff and anti-infinite-loop!
return;
}
cb();
}, {Metadata: meta});
}
gun.server.transport = (function(){
function tran(req, cb){
//console.log(req);
@ -204,6 +102,23 @@
}
tran.post = function(req, cb){ // post is used as patch, sad that patch has such poor support
if(!req.body){ return cb({body: {err: "No body"}}) }
if(req.url.key && Gun.obj.has(req.body, Gun._.soul)){ // key hook!
req.tab = tran.sub.s[req.sub] || {};
req.tab.sub = req.sub;
console.log("key.hook", req.tab);
tran.sub.scribe(req.tab, req.body[Gun._.soul]);
return gun.load(req.body).get(function(frozen){
// NEED to allow a security callback so server can tamper with this!
this.key(req.url.key, function(err, reply){
reply = reply || {};
if(err){ reply.err = err }
reply = {body: reply};
reply.headers = {'Content-Type': tran.json};
reply.headers['Gun-Sub'] = req.tab.sub;
cb(reply);
});
}); // do I need to handle the blank case? :/ Not sure.
}
// raw test for now, no auth:
// should probably load all the nodes first? YES.
var context = gun.union(req.body, function(err, context){ // data safely transformed
@ -327,6 +242,7 @@
tran.sub.scribe = function(tab, soul){
tran.sub.s[tab.sub] = tab;
tab.subs = tab.subs || {};
console.log("meow subscribes", soul);
tab.subs[soul] = tab.subs[soul] || tran.push(soul).event(function(req){
if(!req){ return }
if(!tab){ return this.off() } // resolve any dangling callbacks
@ -407,10 +323,7 @@
opt.hooks = opt.hooks || {};
gun.opt({hooks: {
load: opt.hooks.load || s3.load
,set: opt.hooks.set || s3.set
,key: opt.hooks.key || s3.key
,transport: opt.hooks.transport || gun.server.transport
transport: opt.hooks.transport || gun.server.transport
}}, true);
});
meta.json = 'application/json';
@ -438,5 +351,4 @@
return true;
}
};
module.exports = Gun;
}());

View File

@ -1,16 +0,0 @@
---
applications:
".":
name: gunjs
framework:
name: standalone
info:
mem: 64M
description: Standalone Application
exec:
runtime: node10
command: node init.js
infra: aws
url: http://gunjs.aws.af.cm
mem: 64M
instances: 1

46
on.js
View File

@ -1,46 +0,0 @@
;(function(){
var setImmediate = setImmediate || function(cb){setTimeout(cb,0)}
function On(){
var chain = new Chain();
return chain.$ = function(where){
chain.$[where] = function(fn){
chain.$[where] = fn;
}
chain.where = where;
return chain;
}
}
On.is = function(On){ return (On instanceof On)? true : false }
function Chain(){
if(!(this instanceof Chain)){
return new Chain();
}
}
Chain.chain = Chain.prototype;
Chain.chain.emit = function(a,s,d,f){
var me = this
, where = me.where
, args = Array.prototype.slice.call(arguments);
setImmediate(function(){
if(!me || !me.$ || !me.$[where]){ return }
me.$[where].apply(me, args);
});
return me;
}
if(typeof window !== "undefined"){
window.On = On;
} else {
module.exports = On;
}
;(function(){ // test
var doSomething = function(){
var cb = On();
cb('now').emit(1,2,3);
return cb;
}
doSomething('foo', 'bar').now(function(a,b,c){
console.log("Oh yeah baby", a,b,c);
})
}());
}());

View File

@ -1,5 +1,5 @@
{ "name": "gun"
, "version": "0.0.8"
, "version": "0.0.9"
, "author": "Mark Nadal"
, "description": "Graph engine."
, "engines": {
@ -9,6 +9,7 @@
"mime": "~>1.2.11",
"aws-sdk": "~>2.0.0",
"formidable": "~>1.0.15",
"ws": "~>0.4.32",
"request": "~>2.39.0"
}
, "devDependencies": {

View File

@ -1,2 +0,0 @@
console.log("!!! OPENSHIFT ONLY !!!");
require('./init');

148
shot0.js
View File

@ -1,148 +0,0 @@
module.exports = require('theory')
('shot',function(a){
return function(opt){
opt = opt || {};
opt.path = opt.path || '.'
opt.batch = opt.batch || 0;
opt.throttle = opt.throttle || 0;
opt.src = opt.src || (this && this.com) || '';
opt.cache = a.num.is(opt.cache)? opt.cache : opt.cache || 1;
if(root.node){ return require(opt.path+'/shots0')(opt); }
var u, shot = {},
store = window.amplify && window.amplify.store? amplify.store
: function(src, data){
if(data === u){ return store[src] }
return store[src] = data;
}
store.batch = [];
store.last = a.time.now();
store.list = function(){
var g = store(a.gun.event) || {}
, z = function(l,g,i){
if(i !== 0 && !i){ return }
if(!l || !l[i]){ return }
shot.fire(l[i], 1);
console.log("re-sent", l[i]);
a.time.wait(function(){ z(l,g,i+1) },1);
}
a.obj(g).each(function(l,g){
z(l,g,0);
});
}
store.sort = function(A,B){
if(!A || !B){ return 0 }
A = ((A||{})._||{})[a.gun._.ham]; B = ((B||{})._||{})[a.gun._.ham];
if(A < B){ return -1 }
else if(A > B){ return 1 }
else { return 0 }
}
store.add = function(m, g, b){
if(!m){ return }
g = '_' + (a(g,'at') || g || a(m,'where.at') || m.where);
var gs = store(a.gun.event) || {}
, when = shot.when(m);
gs[g] = gs[g] || [];
if(a.list(gs[g]).each(function(v){
var w = shot.when(v);
if(w === when){
return true;
}
})){ return 2; } // already
if(opt.batch && a.list.is(b)){ b.push(m) }
gs[g].push(m);
store(a.gun.event, gs);
return gs[g];
}
store.del = function(m, g){
if(!m){ return }
var gs = store(a.gun.event) || {}
, when = shot.when(m);
g = '_'+(m.where.at || m.where || g);
console.log("clear queue", g, m);
gs[g] = gs[g] || [];
gs[g] = a.list(gs[g]).each(function(v,i,t){
var w = shot.when(v);
if(w === when){
return;
}
t(v);
});
store(a.gun.event, gs);
}
store.set = function(key, val){
var s = store(a.gun.event) || {};
s[key] = val;
store(a.gun.event, s);
}
store.get = function(key, cb){
var s = store(a.gun.event) || {};
s = s[key];
if(cb){
return cb(null, s);
}
return s;
};
a.gun.shots(shot.fire = function(m, r){
if(!m || !m.where){ return }
if(!r){
if(store.add(m, m.where, store.batch) === 2){
return;
}
}
if(opt.src && opt.src.send){
m = opt.src.meta(m);
if(!m.what || !m.where || !m.when){ return }
console.log("to server!", m);
return opt.src.send(m);
}
return; // below should be a fallback. TODO: Unfinished!
});
shot.when = function(m){ return a(m,'what._.'+a.gun._.ham) || a(m,'_.'+a.gun._.ham) || m.when }
shot.load = function(where,cb,o){
if(!where){ return }
o = o || {};
var m = {what: where, how: {gun:3}}
, g = a.gun.magazine[where] || store.get(where);
g = a.fns.is(g)? g : a.obj.is(g)? a.gun(where, g) : null;
if(g){
//cb(g);
}
//console.log("!!! ASK !!!");
if(opt.src && opt.src.ask){
opt.src.ask(m,function(m){
if(g){
//console.log("!!! double load !!!");
//return; // prevent load from calling twice! Add sync comparison.
}
if(!m || !m.what){ cb(null) }
if(o.cache !== 0){
if(o.cache || opt.cache){ // make options more configurable.
store.set(where, m.what);
}
}
m = a.gun(where, m.what);
cb(m);
});
}
}
shot.spray = function(filter){
if(filter && filter.how){
shot.spray.action(filter);
return shot;
}
if(a.fns.is(filter)){
shot.spray.action = filter;
return shot;
}
return shot.spray.action;
}
shot.spray.action = function(m){
if(!m || !m.how || !m.how.gun){ return }
if(m.how.gun === -1){
store.del(m);
}
}
store.list();
return shot;
}
},['./gun0'])

305
shots0.js
View File

@ -1,305 +0,0 @@
module.exports = require('theory')
('shot',function(a){
var s3 = require(__dirname+'/gate/s3')
, store = require(__dirname+'/gate/redis');
function shot(opt){
opt = opt || {};
var u, shot = {};
opt.path = opt.path || '.'
opt.batch = opt.batch || 10;
opt.throttle = opt.throttle || 15;
opt.src = opt.src || (this && this.com) || '';
opt.redis = opt.redis || {};
opt.redis.max = a.num.is(opt.redis.max)? opt.redis.max : .8;
opt.redis.Max = Math.floor(require('os').totalmem() * opt.redis.max);
opt.redis.append = a.obj(opt.redis).has('append')? opt.redis.append : true;
opt.redis.expire = opt.redis.expire || 60*15;
opt.redis.config = function(){
if(opt.redis.config.done === 0){ return }
opt.redis.config.done = 3;
var reply = function(e,r){
if(e){ return }
opt.redis.config.done -= 1;
};
if(opt.redis.max){
store.client.config('set','maxmemory',opt.redis.Max, reply);
store.client.config('set','maxmemory-policy','allkeys-lru', reply);
}
if(opt.redis.append){
store.client.config('set','appendonly','yes', reply);
}
}
opt.s3 = opt.s3 || {};
opt.s3.Bucket = a.text.is(opt.s3.bucket)? opt.s3.bucket : (process.env.s3Bucket || '');
opt.s3.bucket = a.fns.is(opt.s3.bucket)? opt.s3.bucket : function(key){
return opt.s3.Bucket || a.text(key).clip('/',0,1);
}
opt.s3.key = a.fns.is(opt.s3.key)? opt.s3.key : function(key){
if(key.slice(0, opt.s3.Bucket.length) === opt.s3.Bucket){
key = key.slice(opt.s3.Bucket.length)||'';
if(key.charAt(0) === '/'){
key = key.slice(1);
}
}
return key;
}
store.batch = [];
store.last = a.time.now();
store.push = function(key, score, val, cb){
if(!val){ return }
store.client.zadd(key, score, val, function(e,r){
if(e){
store.clienf.zadd(key, score, val, cb);
return;
}
if(cb){ cb(e,r) }
});
}
store.when = function(m){ return a(m,'what._.'+a.gun._.ham) || a(m,'_.'+a.gun._.ham) || m.when }
store.where = function(m){ return a.text.is(m)? m : a.text.is(m.where)? m.where : m.where.at }
store.add = function(m, g){
if(!m){ return }
g = '_' + (g || a(m,'where.at') || m.where);
store.push(g, store.when(m) || 0, a.text.ify(m));
}
store.del = function(m, g){
}
store.sort = function(A,B){
if(!A || !B){ return 0 }
A = A.w; B = B.w;
if(A < B){ return -1 }
else if(A > B){ return 1 }
else { return 0 }
}
store.batching = 0;
store.batched = {};
store.batch = {};
store.persisted = {};
store.wait = null;
store.stay = function(key, val, cb){
store.batching += 1;
store.batch[key] = val;
(store.batched[key] = store.batched[key]||[]).push(cb);
if(opt.batch < store.batching){
return store.stay.now();
}
if(!opt.throttle){
return store.stay.now();
}
store.wait = store.wait || a.time.wait(store.stay.now, opt.throttle * 1000); // to seconds
}
store.stay.now = function(){
store.batching = 0;
a.time.stop(store.wait);
store.wait = null;
a.obj(store.batch).each(function(g,where){
if(!g || !where){ return }
//console.log('*************** save', where, '*******************');
store.stay.put(where,g,function(e,r){
a.list(store.batched[where]).each(function(cb){
if(a.fns.is(cb)){ cb(e,r) }
console.log('*** saved ***');
});
console.log(store.batched[where]);
delete store.batched[where];
});
});
}
store.stay.put = function(where,obj,cb){
s3(opt.s3.bucket(where)).put(opt.s3.key(where),obj,function(e,r){
if(!e){ store.persisted[where] = 's3' }
if(a.fns.is(cb)){ cb(e,r) }
});
}
store.set = function(key, value, cb, fn){
opt.redis.config();
var val = a.text.is(value)? value : a.text.ify(value);
if(a.fns.is(fn)){ store.stay(key, value, fn) }
//console.log("potential setex:", key, opt.redis.expire, val);
if(opt.redis.max){
store.client.set(key, val, function(e,r){
if(e){
store.clienf.setex(key, opt.redis.expire, val, cb);
return;
}
if(cb){ cb(e,r) }
});
} else {
store.client.setex(key, opt.redis.expire, val, function(e,r){
if(e){
store.clienf.setex(key, opt.redis.expire, val, cb);
return;
}
if(cb){ cb(e,r) }
});
}
}
store.get = function(key, cb){
store.clienf.get(key, function(e,r){
if(e || !r){ return store.client.get(key, cb) }
if(cb){ cb(e,r) }
});
}
shot.load = function(where,cb,o){
//console.log("shot.load >", where);
if(!where){ return }
where = store.where(where);
if(!a.text.is(where)){ return }
if(a.fns.is(a.gun.magazine[where])){
console.log('via memory', where);
cb(a.gun.magazine[where], null); // TODO: Need to clear queue these at some point, too!
return;
}
if(opt.src && opt.src.send){
//console.log("Getting and subscribe");
opt.src.send({where:{on: where}, how: {gun: 2}});
}
store.get(where, function(e,r){
if(e || !r){
return s3(opt.s3.bucket(where)).get(opt.s3.key(where),function(e,r,t){
console.log('via s3', where); if(e){ console.log(e) }
if(e || !r){ return cb(null, e) }
store.persisted[where] = 's3';
store.set(where, (t || a.text.ify(r)));
r = shot.load.action(where,r); //a.gun(where,r);
cb(r, e);
},o);
}
console.log('via redis', where);
r = a.obj.ify(r);
r = shot.load.action(where,r); //a.gun(where,r);
cb(r,e);
});
}
shot.load.action = function(w,o){
if(!w || !o){ return }
return a.gun(w,o);
}
shot.spray = function(m){
if(m && m.how){
shot.spray.action(m);
return shot;
}
if(a.fns.is(m)){
shot.spray.transform = m;
return shot.spray.action;
}
return shot.spray.action;
}
shot.spray.transform = function(g,m,d){if(d){d()}}
shot.spray.action = function(m){
console.log("gun spray ---->", m, (opt.src && opt.src.way? opt.src.way : null));
if(!m || !m.how){ return }
var where = store.where(m);
if(m.how.gun === -2){
console.log("gun data from others", m);
if(m && m.what && m.what.session){ console.log(m.what.session) }
return;
}
if(m.how.gun === 2){
if(!a.fns.is(a.gun.magazine[where])){
return;
}
if(opt.src && opt.src.send){
console.log("gun subscribe sync", m);
opt.src.send({what: a.gun.magazine[where](), where: where, how: {gun: -(m.how.gun||2)}});
}
return;
}
if(m.how.gun === 3){
shot.load(m.what, function(g,e){
shot.pump.action(g, m, function(){ // receive custom edited copy here and send it down instead.
if(!opt.src || !opt.src.reply){ return }
m.what = a.fns.is(g)? g() : {};
m.how.gun = -(m.how.gun||3);
opt.src.reply(m);
}, e);
});
return;
}
if(!where){ return }
store.add(m);
var n = a.obj.copy(m);
shot.load(where, function(g,e){
var done = function(){
var u, s, w = store.when(m) || 0, r = {}, cb;
m.how.gun = -(m.how.gun||1);
g = a.fns.is(g)? g : (a.gun.magazine[where] || function(){});
a.obj(m.what).each(function(v,p){
if(g(p,v,w) === u){
r[p] = 0; // Error code
return;
} s = true;
});
m.what = r;
cb = function(){
if(!opt.src || !opt.src.reply || m.where.mid){ return }
opt.src.reply(m);
console.log('reply', m);
}
if(!s){ return cb() }
store.set(where, g(), null, cb);
};
done.end = function(){};
shot.spray.transform(g, m, done, e);
});
if(n.where && !n.where.mid && opt.src.send){
n.who = {};
opt.src.send(n);
}
}
if(opt.src && opt.src.on){
opt.src.on(shot.spray.action);
}
shot.pump = function(fn){
shot.pump.action = fn || shot.pump.action;
return shot;
}
shot.pump.action = function(g,m,d){if(d){d()}}
shot.server = function(req,res){
console.log('shot server', req);
if(!req || !res){ return }
var b = shot.server.get(req);
if(!b || !b.b){ return }
b = a.obj.ify((b||{}).b);
if(a.obj.is(b)){ b = [b] }
if(!a.list.is(b)){ return }
//console.log('gun >>>>>>');
a.list(b).each(function(v,i){
//console.log(v);
});
//console.log('<<<<<< gun');
if(req.how && req.when && req.who && a.fns.is(res)){
req.what.body = {ok:1};
res(req);
}
return true;
}
shot.server.get = function(m){
return !a.obj.empty(a(m,'what.form'))? a(m,'what.form')
: !a.obj.empty(a(m,'what.url.query'))? a(m,'what.url.query')
: false ;
};
a.gun.shots(function(m){
var w;
if(!store.persisted[w = store.where(m)]){
if(opt.src && opt.src.send){
//console.log("made and subscribed", m);
opt.src.send({where:{on: w}, how: {gun: 2}})
}
store.stay.put(w, m.what, function(e,r){
//console.log("---> gun shots", m, "new graph saved!");
});
return;
}
if(opt.src && opt.src.send){
opt.src.send(m);
}
});
shot.gun = a.gun;
return shot;
}
shot.gun = a.gun;
return shot;
},[__dirname+'/gun0'])

View File

@ -147,6 +147,114 @@ describe('Gun', function(){
expect(Gun.obj.map({a:'z',b:3,c:'x'},function(v,i,t){ if(v===3){ return 0 }})).to.be(0);
});
});
describe('Functions', function(){
it('sum',function(done){
var obj = {a:2, b:2, c:3, d: 9};
Gun.obj.map(obj, function(num, key){
setTimeout(this.add(function(){
this.sum(null, num * num);
}, key), parseInt((""+Math.random()).substring(2,5)));
}, Gun.fns.sum(function(err, val){
expect(val.a).to.eql(4);
expect(val.b).to.eql(4);
expect(val.c).to.eql(9);
expect(val.d).to.eql(81);
done();
}));
});
});
describe('Gun Safety', function(){
var gun = Gun();
it('is',function(){
expect(Gun.is(gun)).to.be(true);
expect(Gun.is(true)).to.be(false);
expect(Gun.is(false)).to.be(false);
expect(Gun.is(0)).to.be(false);
expect(Gun.is(1)).to.be(false);
expect(Gun.is('')).to.be(false);
expect(Gun.is('a')).to.be(false);
expect(Gun.is(Infinity)).to.be(false);
expect(Gun.is(NaN)).to.be(false);
expect(Gun.is([])).to.be(false);
expect(Gun.is([1])).to.be(false);
expect(Gun.is({})).to.be(false);
expect(Gun.is({a:1})).to.be(false);
expect(Gun.is(function(){})).to.be(false);
});
it('is value',function(){
expect(Gun.is.value(false)).to.be(true);
expect(Gun.is.value(true)).to.be(true);
expect(Gun.is.value(0)).to.be(true);
expect(Gun.is.value(1)).to.be(true);
expect(Gun.is.value('')).to.be(true);
expect(Gun.is.value('a')).to.be(true);
expect(Gun.is.value({'#':'somesoulidhere'})).to.be('somesoulidhere');
expect(Gun.is.value({'#':'somesoulidhere', and: 'nope'})).to.be(false);
expect(Gun.is.value(Infinity)).to.be(false); // boohoo :(
expect(Gun.is.value(NaN)).to.be(false);
expect(Gun.is.value([])).to.be(false);
expect(Gun.is.value([1])).to.be(false);
expect(Gun.is.value({})).to.be(false);
expect(Gun.is.value({a:1})).to.be(false);
expect(Gun.is.value(function(){})).to.be(false);
});
it('is soul',function(){
expect(Gun.is.soul({'#':'somesoulidhere'})).to.be('somesoulidhere');
expect(Gun.is.soul({'#':'somethingelsehere'})).to.be('somethingelsehere');
expect(Gun.is.soul({'#':'somesoulidhere', and: 'nope'})).to.be(false);
expect(Gun.is.soul({or: 'nope', '#':'somesoulidhere'})).to.be(false);
expect(Gun.is.soul(false)).to.be(false);
expect(Gun.is.soul(true)).to.be(false);
expect(Gun.is.soul('')).to.be(false);
expect(Gun.is.soul('a')).to.be(false);
expect(Gun.is.soul(0)).to.be(false);
expect(Gun.is.soul(1)).to.be(false);
expect(Gun.is.soul(Infinity)).to.be(false); // boohoo :(
expect(Gun.is.soul(NaN)).to.be(false);
expect(Gun.is.soul([])).to.be(false);
expect(Gun.is.soul([1])).to.be(false);
expect(Gun.is.soul({})).to.be(false);
expect(Gun.is.soul({a:1})).to.be(false);
expect(Gun.is.soul(function(){})).to.be(false);
});
it('is node',function(){
expect(Gun.is.node({_:{'#':'somesoulidhere'}})).to.be(true);
expect(Gun.is.node({_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}})).to.be(true);
expect(Gun.is.node({_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}, g: Infinity})).to.be(false);
expect(Gun.is.node({_:{'#':'somesoulidhere'}, a:0, b: 1, z: NaN, c: '', d: 'e'})).to.be(false);
expect(Gun.is.node({_:{'#':'somesoulidhere'}, a:0, b: 1, y: {_: 'cool'}, c: '', d: 'e'})).to.be(false);
expect(Gun.is.node({_:{'#':'somesoulidhere'}, a:0, b: 1, x: [], c: '', d: 'e'})).to.be(false);
expect(Gun.is.node({})).to.be(false);
expect(Gun.is.node({a:1})).to.be(false);
expect(Gun.is.node({_:{}})).to.be(false);
expect(Gun.is.node({_:{}, a:1})).to.be(false);
expect(Gun.is.node({'#':'somesoulidhere'})).to.be(false);
});
it('is graph',function(){
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}}})).to.be(true);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(true);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(true);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}})).to.be(true);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, foo: 1, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, foo: {}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, foo: {_:{'#':'FOO'}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, foo: {_:{}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: Infinity, c: '', d: 'e', f: {'#':'somethingelsehere'}}})).to.be(false);
expect(Gun.is.graph({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: Infinity, c: '', d: 'e', f: {'#':'somethingelsehere'}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false);
expect(Gun.is.graph({_:{'#':'somesoulidhere'}})).to.be(false);
expect(Gun.is.graph({_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}})).to.be(false);
expect(Gun.is.graph({_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}, g: Infinity})).to.be(false);
expect(Gun.is.graph({_:{'#':'somesoulidhere'}, a:0, b: 1, z: NaN, c: '', d: 'e'})).to.be(false);
expect(Gun.is.graph({_:{'#':'somesoulidhere'}, a:0, b: 1, y: {_: 'cool'}, c: '', d: 'e'})).to.be(false);
expect(Gun.is.graph({_:{'#':'somesoulidhere'}, a:0, b: 1, x: [], c: '', d: 'e'})).to.be(false);
expect(Gun.is.graph({})).to.be(false); // Empty graph is not a graph :(
expect(Gun.is.graph({a:1})).to.be(false);
expect(Gun.is.graph({_:{}})).to.be(false);
expect(Gun.is.graph({_:{}, a:1})).to.be(false);
expect(Gun.is.graph({'#':'somesoulidhere'})).to.be(false);
});
});
});
it('ify', function(){

46
web/deck/deck.html Normal file
View File

@ -0,0 +1,46 @@
<style>
html, body {
margin: 0;
padding: 0;
text-align: center;
font-size: 36pt;
font-family: Verdana, Geneva, sans-serif;
}
</style>
<div style="height: 100%; min-height: 500px; background-color: rgb(241, 90, 34); color: white;">
<div id="e1413969480658t7942" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 413px;
background-image: url('wave.png'); background-color: rgb(108, 197, 195); background-position: 43.1875% 100%; background-repeat: repeat-x;">
<div id="e1414010158000t6484" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 9px;" contenteditable="false">Problem</div>
<div id="e1414009476621t898" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 481px; width: 370px;
background-image: url('whale.png'); background-position: 50% 50%; background-repeat: no-repeat;"></div>
</div>
<div id="e1414009076551t8032" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto 51px; min-height: 100px;">
<br>Hassle to deploy slow databases that are costly to scale</div>
</div>
<div id="e1414009851463t501" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; height: 100%; min-height: 500px;">
<div id="e1414009879758t838" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px; background-color: rgba(0, 0, 0, 0);" contenteditable="false">Solution</div>
<div id="e1414009950683t8894" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; width: 50%; min-width: 200px; max-width: 500px; height: 400px;
background-image: url('../../img/gun-logo.png'); background-position: 50% 50%; background-repeat: no-repeat; background-size: 100%;"></div>
<div id="e1414009972993t897" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px; background-color: rgba(0, 0, 0, 0);" contenteditable="false">the NoDB database</div>
</div>
<div id="e1414010217854t5686" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; height: 100%; min-height: 500px; background-color: black; color: white;
background-image: url('polygen.png'); background-position: 50% 50%; background-repeat: no-repeat; background-size: 100%;">
<div id="e1414010395848t489" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false">How</div>
<div id="e1414010397417t8943" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; height: 500px;"></div>
<div id="e1414010398484t2942" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false">peer to peer algorithms that mimic reality</div>
</div>
<div id="e1414010478794t8943" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; height: 100%; min-height: 500px;">
<div id="e1414010488753t8274" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false">Now</div>
<div id="e1414010489729t8174" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; height: 400px;
background-image: url('stats.png'); background-position: 50% 50%; background-repeat: no-repeat; background-size: 100%;"></div>
<div id="e1414010490585t2896" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false">fastest growing trends ever in software history</div>
</div>
<div id="e1414010542879t6487" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 500px; height: 100%; background-color: black; color: white;
background-image: url('team2.jpg'); background-position: 39.8610229492188% 17.7705977382876%; background-repeat: no-repeat; background-size: 100%;">
<div id="e1414010614360t886" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false">Team</div>
<div id="e1414010615329t6812" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; height: 400px;"></div>
<div id="e1414010616147t6367" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false"></div>
</div>
<div id="e1414010638042t831" class="" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 500px; height: 100%;" contenteditable="false">
<div id="e1414010679930t7366" class="create-evyt" style="position: relative; display: block; overflow: hidden; padding: 10px; margin: 0px auto; min-height: 100px;" contenteditable="false">we@gunDB.io are raising $500k</div>
</div>

BIN
web/deck/team2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 KiB

BIN
web/deck/wave.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
web/deck/whale.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 113 KiB

View File

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 81 KiB

View File

@ -1,3 +1,9 @@
HOOKS:
- TRANSPORT:
Has to basically re-implement set/load/key over some transport.
REMEMBER that you have to subscribe on all set/load/key (especially key).
Notes:
Messaging

210
web/time.html Normal file
View File

@ -0,0 +1,210 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="../gun.js"></script>
<link id="style" rel="stylesheet" href="https://yandex.st/highlightjs/8.0/styles/sunburst.min.css">
<script src="https://yandex.st/highlightjs/8.0/highlight.min.js"></script>
<script src="https://dl.dropboxusercontent.com/u/4374976/random/phrase.js"></script>
</head>
<body>
<style>
@import url(http://fonts.googleapis.com/css?family=Dosis|Poiret+One|Oxygen);
html, body {
font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
.center {
text-align: center;
}
.lean {
font-family: 'Poiret One', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
.clean {
font-family: 'Dosis', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
.crisp {
font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
pre {
background-color: black;
border: 1px dashed white;
color: white;
line-height: 1.5em;
padding: 1em;
overflow: hidden;
}
button {
border: none;
color: white;
background: skyblue;
padding: 1em;
cursor: pointer;
}
input {
background: transparent;
border: 2px dashed grey;
padding: 1em;
}
.step {
display: none;
}
.step:target {
display: block;
}
.grid {
text-align: center;
}
.unit {
display: inline-block;
}
.learn {
min-width: 250px;
max-width: 400px;
width: 30%;
padding: 2em;
}
</style>
<div class="center">
<h1 class="lean">Easiest . Database . Ever</h1>
<h2 class="lean">Scale without pain, because it is decentralized.</h2>
</div>
<div id="steps">
<div id="step1">
As easy as 1, 2, 3!
<ol>
<li>Connect to a gun server.</li>
<li>Save some data.</li>
<li>Create a key to open it up later.</li>
</ol>
<pre>var gun = Gun('http://localhost:8888/gun');
gun.set({hello: 'world'}).key('<span class="random">my/first/data</span>');</pre>
<a href="#step2" class="run"><button>
Try it Now!
</button></a>
<small>Disclaimer: This is a demo only! Data is deleted every 24 hours.</small>
<!--
<div>
Already have a key? Then
<input placeholder="copy and paste it into here!">
</div>
-->
</div>
<div id="step2" class="step">
Let's test to see if the data got saved.
<ol>
<li><a id="parallel" href="?key=" target="_blank">Open this page</a> in another browser tab.</li>
<li>Now you'll see <b class="random" style="color: crimson;">my/first/data</b> load over there.
<li>Meanwhile, this textarea will wait for realtime updates from the other tab:</li>
</ol>
<textarea style="width: 100%; height: 100px;">// Your data will log here!</textarea>
The next level will be unlocked when you complete the realtime sync between tabs.
</div>
<div id="step3" class="step">
<pre>var gun = Gun('http://localhost:8888/gun');
gun.load('<span class="random">my/first/data</span>', function(data){
$('textarea').text(demo.print(data));
});</pre>
<a href="#step4" class="run"><button>
Run the Code!
</button></a> Does the key match from the previous tab?
<textarea style="width: 100%; height: 100px;">// Your data will log here!</textarea>
</div>
<div id="step4" class="step">
Now let's listen to realtime updates, and change the value on the 'hello' field.
<pre>gun.load('<span class="random">my/first/data</span>')
.on(function(updates){
$('textarea').text(demo.print(updates));
}).path('hello').set('You!');</pre>
<a class="run"><button>
Let's do This!
</button></a>
<textarea style="width: 100%; height: 100px;">// Your data will log here!</textarea>
</div>
</div>
<div class="grid">
<div class="learn unit center">
<h1 class="lean">Did you know?</h1>
<h2 class="lean">GUN is lightning fast, cause it runs in memory.</h2>
Click to <a href="#step2" class="run"><button>
See How
</button></a> persistence works.
</div>
<div class="learn unit center">
<h1 class="lean">Guess what!</h1>
<h2 class="lean">GUN is the only database with realtime push notifications.</h2>
Learn <a href="#step2" class="run"><button>
How it Works
</button></a>.
</div>
<div class="learn unit center">
<h1 class="lean">Have Big Data?</h1>
<h2 class="lean">GUN tranforms it into <i>meaningful data</i>, with regular JS.</h2>
Discover <a href="#step2" class="run"><button>
How To
</button></a> do a graph search.
</div>
</div>
<script>
$(function(){
var demo = {}, gun;
window.demo = demo;
demo.key = location.search.split('=')[1];
demo.random = demo.key || random_phrase.noun() +'/'+ random_phrase.verb() +'/'+ random_phrase.adjective() +'/'+ random_phrase.noun() +'/'+ random_phrase.adverb();
$(".random").text(demo.random);
$('pre').each(function(){
$(this).html(hljs.highlight('javascript', $(this).text()).value);
});
$('#step1').addClass((demo.key || location.hash)? 'step' : '').find('a').first().click(function(){
$('#step1').addClass('step');
});
$('#parallel').attr('href', '?key=' + demo.random + '#step3');
$(".run").click(function(){
var code = $(this).closest('.step').attr('id');
if(!code || !demo[code]){ return } // something went wrong!
demo[code]();
});
demo.step0 = function(){
gun = window.gun = window.gun || Gun('http://localhost:8888/gun');
}
demo.step1 = function(){
demo.step0();
gun.set({hello: 'world'}).key(demo.random);
// and also do this, so we can unlock!
gun.load(demo.random)
.on(function(updates){
$('textarea').text(demo.print(updates));
// unlock level 5!
});
}
demo.step2 = function(){} // no step 2
demo.step3 = function(){
demo.step0();
gun.load(demo.random, function(data){
$('textarea').text(demo.print(data));
});
}
demo.step4 = function(){
demo.step0();
gun.load(demo.random)
.on(function(updates){
$('textarea').text(demo.print(updates));
}).path('hello').set('You!');
}
demo.print = function(data){
if(!data){ return }
delete data._; // this is gun specific metadata that we don't want to print.
return JSON.stringify(data, null, 2);
}
});
</script>
<a href="https://github.com/amark/gun"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
</body>
</html>