diff --git a/examples/chat/index.html b/examples/chat/index.html index 9166d854..050d8003 100644 --- a/examples/chat/index.html +++ b/examples/chat/index.html @@ -1,66 +1,104 @@ - - - + + + - - -
- - - -
- - + #converse .box { + margin-bottom: 0.2em; + padding: 1em; + border-radius: 0.1em; + } + #converse b:after { + content: " "; + } + #converse li .when { + position: absolute; + top: 0; + right: -2em; + padding: 0.5em 1em; + background: rgba(100%,100%,100%,0.9); + opacity: 0; + } + #converse li:hover .when { + opacity: 1; + right: 0em; + } + .poiret { + font-family: 'Poiret One', sans-serif; + } + .large { + font-size: 200%; + } + #converse .what, #converse .who { + cursor: text; + outline: none; + display: inline; + min-width: 1em; + padding-left: 1px; + } + [contentEditable=true]:empty:not(:focus):before{ + content:attr(data-text) + } + +
+
Have a Conversation...
+
+ +
+
+
send
+ +

+
+
+
+
  • 0
  • +
    +
    +
    + + + + diff --git a/examples/chat/spam.js b/examples/chat/spam.js deleted file mode 100644 index 1adfcd18..00000000 --- a/examples/chat/spam.js +++ /dev/null @@ -1,10 +0,0 @@ -function spam(){ - spam.start = true; spam.lock = false; - if(spam.count >= 100){ return } - var $f = $('form'); - $('.what', $f).value = ++spam.count; - $f.onsubmit(); - setTimeout(spam, 0); -}; spam.count = 0; spam.lock = true; - -alert("ADD THIS LINE TO THE TOP OF THE MAP.VAL CALLBACK: `if(!spam.lock && !spam.start){ spam() }`"); \ No newline at end of file diff --git a/examples/express-auth.js b/examples/express-auth.js deleted file mode 100644 index c48061ac..00000000 --- a/examples/express-auth.js +++ /dev/null @@ -1,30 +0,0 @@ -console.log("If modules not found, run `npm install` in /example folder!"); // git subtree push -P examples heroku master // OR // git subtree split -P examples master && git push heroku [['HASH']]:master --force -var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || process.argv[2] || 80; - -var express = require('express'); -var app = express(); - -var Gun = require('gun'); -var gun = Gun({ - file: 'data.json', - s3: { - key: '', // AWS Access Key - secret: '', // AWS Secret Token - bucket: '' // The bucket you want to save into - } -}); - -gun.wsp(app/*, function(req, res, next){ - console.log("auth!", req, req.body['#']); - if('get' === req.method){ - if('example/todo/data' === req.body['#']){ - next(req, res); - } - } - if('put' === req.method){ - res({body: {err: "Permission denied!"}}); - } -}*/); -app.use(express.static(__dirname)).listen(port); - -console.log('Server started on port ' + port + ' with /gun'); \ No newline at end of file diff --git a/examples/game/nts.html b/examples/game/nts.html new file mode 100644 index 00000000..c8a366af --- /dev/null +++ b/examples/game/nts.html @@ -0,0 +1,19 @@ + + + + + +

    + + + + + \ No newline at end of file diff --git a/examples/game/space.html b/examples/game/space.html new file mode 100644 index 00000000..6dba5527 --- /dev/null +++ b/examples/game/space.html @@ -0,0 +1,254 @@ + + + + +
    +
    +
    +
    +
    + + + + + + \ No newline at end of file diff --git a/examples/index.html b/examples/index.html index 21f366e8..d8d5274a 100644 --- a/examples/index.html +++ b/examples/index.html @@ -6,18 +6,23 @@ -

    Examples Directory

    + - + - + diff --git a/examples/react.html b/examples/react.html deleted file mode 100644 index e17eab76..00000000 --- a/examples/react.html +++ /dev/null @@ -1,175 +0,0 @@ - - - -gun - react examples - - - -
    - - - - - - - diff --git a/examples/style.css b/examples/style.css new file mode 100644 index 00000000..dd1295d0 --- /dev/null +++ b/examples/style.css @@ -0,0 +1,279 @@ +@import url(https://fonts.googleapis.com/css?family=Oxygen); + +html, body { + margin: 0; + padding: 0; + font-family: 'Oxygen', 'Trebuchet MS', arial; + position: relative; +} + +div, ul, li, form, p, span, input, textarea { + margin: 0; + padding: 0; + position: relative; + overflow: hidden; + -webkit-transition: all 0.3s; + transition: all 0.3s; + box-sizing: border-box; +} + +ul, li { + list-style: none; +} + +body { + font-size: 18pt; +} + +.model { display: none } +.mid { margin-left: auto; margin-right: auto; } +.row { width: 100%; } +.col { max-width: 33em; } +input, textarea { + border: none; + width: 100%; +} + +.none { + display: none; +} + +.page { + width: 100%; + min-height: 100vh; +} + +.red { + background: #ea3224; +} +.green { + background: #33cc33; +} +.blue { + background: #4D79D8; +} +.yellow { + background: #f2b919; +} +.black { + background: black; +} +.white { + background: white; +} + +.redt { + color: #ea3224; +} +.greent { + color: #33cc33; +} +.bluet { + color: #4D79D8; +} +.yellowt { + color: #f2b919; +} +.blackt { + color: black; +} +.whitet { + color: white; +} + +.pad { + margin: 5% auto; + min-width: 250px; + width: 95%; + max-width: 50em; +} + +.right { + float: right; +} +.left { + float: left; +} + +.act { + display: block; + font-weight: normal; + text-decoration: none; + -webkit-transition: all 0.3s; + transition: all 0.3s; + cursor: pointer; +} + +.rubric { + font-size: 150%; +} +.center { + text-align: center; +} + +.jot { + border-bottom: 1px dashed #95B2CA; +} +.sap { + border-radius: 0.1em; +} + +.hue { + background: #4D79D8; + -webkit-animation: hue 900s infinite; + animation: hue 900s infinite; +} + +@keyframes hue { + 0% {background: #4D79D8;} + 25% {background: #33cc33;} + 50% {background: #f2b919;} + 75% {background: #ea3224;} + 100% {background: #4D79D8;} +} @-webkit-keyframes hue { + 0% {background: #4D79D8;} + 25% {background: #33cc33;} + 50% {background: #f2b919;} + 75% {background: #ea3224;} + 100% {background: #4D79D8;} +} + +.huet { + color: #4D79D8; + -webkit-animation: huet 900s infinite; + animation: huet 900s infinite; +} + +@keyframes huet { + 0% {color: #4D79D8;} + 25% {color: #33cc33;} + 50% {color: #f2b919;} + 75% {color: #ea3224;} + 100% {color: #4D79D8;} +} @-webkit-keyframes huet { + 0% {color: #4D79D8;} + 25% {color: #33cc33;} + 50% {color: #f2b919;} + 75% {color: #ea3224;} + 100% {color: #4D79D8;} +} + +.hue2 { + background: #ea3224; + -webkit-animation: hue2 900s infinite; + animation: hue2 900s infinite; +} + +@keyframes hue2 { + 0% {background: #ea3224;} + 25% {background: #4D79D8;} + 50% {background: #33cc33;} + 75% {background: #f2b919;} + 100% {background: #ea3224;} +} @-webkit-keyframes hue2 { + 0% {background: #ea3224;} + 25% {background: #4D79D8;} + 50% {background: #33cc33;} + 75% {background: #f2b919;} + 100% {background: #ea3224;} +} + +.huet2 { + color: #ea3224; + -webkit-animation: huet2 900s infinite; + animation: huet2 900s infinite; +} + +@keyframes huet2 { + 0% {color: #ea3224;} + 25% {color: #4D79D8;} + 50% {color: #33cc33;} + 75% {color: #f2b919;} + 100% {color: #ea3224;} +} @-webkit-keyframes huet2 { + 0% {color: #ea3224;} + 25% {color: #4D79D8;} + 50% {color: #33cc33;} + 75% {color: #f2b919;} + 100% {color: #ea3224;} +} + +.hue3 { + background: #33cc33; + -webkit-animation: hue3 900s infinite; + animation: hue3 900s infinite; +} + +@keyframes hue3 { + 0% {background: #33cc33;} + 25% {background: #f2b919;} + 50% {background: #ea3224;} + 75% {background: #4D79D8;} + 100% {background: #33cc33;} +} @-webkit-keyframes hue3 { + 0% {background: #33cc33;} + 25% {background: #f2b919;} + 50% {background: #ea3224;} + 75% {background: #4D79D8;} + 100% {background: #33cc33;} +} + +.huet3 { + color: #33cc33; + -webkit-animation: huet3 900s infinite; + animation: huet3 900s infinite; +} + +@keyframes huet3 { + 0% {color: #33cc33;} + 25% {color: #f2b919;} + 50% {color: #ea3224;} + 75% {color: #4D79D8;} + 100% {color: #33cc33;} +} @-webkit-keyframes huet3 { + 0% {color: #33cc33;} + 25% {color: #f2b919;} + 50% {color: #ea3224;} + 75% {color: #4D79D8;} + 100% {color: #33cc33;} +} + +.hue4 { + background: #f2b919; + -webkit-animation: hue4 900s infinite; + animation: hue4 900s infinite; +} + +@keyframes hue4 { + 0% {background: #f2b919;} + 25% {background: #ea3224;} + 50% {background: #4D79D8;} + 75% {background: #33cc33;} + 100% {background: #f2b919;} +} @-webkit-keyframes hue4 { + 0% {background: #f2b919;} + 25% {background: #ea3224;} + 50% {background: #4D79D8;} + 75% {background: #33cc33;} + 100% {background: #f2b919;} +} + +.huet4 { + color: #f2b919; + -webkit-animation: huet4 900s infinite; + animation: huet4 900s infinite; +} + +@keyframes huet4 { + 0% {color: #f2b919;} + 25% {color: #ea3224;} + 50% {color: #4D79D8;} + 75% {color: #33cc33;} + 100% {color: #f2b919;} +} @-webkit-keyframes huet4 { + 0% {color: #f2b919;} + 25% {color: #ea3224;} + 50% {color: #4D79D8;} + 75% {color: #33cc33;} + 100% {color: #f2b919;} +} \ No newline at end of file diff --git a/examples/todo/index.html b/examples/todo/index.html index 327de058..4b23cc0c 100644 --- a/examples/todo/index.html +++ b/examples/todo/index.html @@ -1,37 +1,78 @@ + + + + + -

    ToDo List

    - -
    - - - - - - - + #think li { + width: 90%; + margin-top: 0.3em; + border-bottom: 1px dashed white; + } + #think .add { + width: 1em; + height: 1em; + line-height: 1em; + padding: 0.5em; + font-family: Tahoma, arial; + text-align: center; + border-radius: 50%; + } + #think ul, #think li { + list-style-type: circle; + margin-left: 0.5em; + } + +
    +
    +
    Add a Thought...
    + + +
    + +
    + + + + + + + \ No newline at end of file diff --git a/gun.js b/gun.js index 2ac75c7a..c8e6ed77 100644 --- a/gun.js +++ b/gun.js @@ -549,13 +549,14 @@ t = time(); } if(last < t){ - return N = 0, last = t; + return N = 0, last = t + State.drift; } - return last = t + ((N += 1) / D); + return last = t + ((N += 1) / D) + State.drift; } var time = Type.time.is, last = -Infinity, N = 0, D = 1000; // WARNING! In the future, on machines that are D times faster than 2016AD machines, you will want to increase D by another several orders of magnitude so the processing speed never out paces the decimal resolution (increasing an integer effects the state accuracy). var perf = (typeof performance !== 'undefined')? (performance.timing && performance) : false, start = (perf && perf.timing && perf.timing.navigationStart) || (perf = false); State._ = '>'; + State.drift = 0; State.ify = function(n, f, s, v, soul){ // put a field's state on a node. if(!n || !n[N_]){ // reject if it is not node-like. if(!soul){ // unless they passed a soul @@ -673,7 +674,7 @@ if(!(is = valid(v,f,n, at,env))){ return } if(!f){ at.node = at.node || n || {}; - if(obj_has(v, Node._)){ + if(obj_has(v, Node._) && !Gun.is(v)){ at.node._ = obj_copy(v._); } at.node = Node.soul.ify(at.node, Val.rel.is(at.rel)); diff --git a/lib/nts.js b/lib/nts.js index 9075debf..c1e251cf 100644 --- a/lib/nts.js +++ b/lib/nts.js @@ -1,25 +1,46 @@ -Gun.on('opt').event(function(gun, opt){ - if(!gun.tab || !gun.tab.request){ return } - Gun.time.now.drift = 0; - function ping(){ - Gun.obj.map(opt.peers || gun.__.opt.peers, function(peer, url){ - var NTS = {}; - NTS.start = Gun.time.now(); - gun.tab.request(url, null, function(err, reply){ - if(err || !reply || !reply.body){ - return console.log("Network Time Synchronization not supported", err, (reply || {}).body); - } - NTS.end = Gun.time.now(); - NTS.latency = (NTS.end - NTS.start)/2; - if(!Gun.obj.has(reply.body, 'time')){ return } - NTS.calc = NTS.latency + reply.body.time; - Gun.time.now.drift -= (NTS.end - NTS.calc)/2; - setTimeout(ping, 250); - }, {url: {pathname: '.nts'}}); +;(function(){ + + var env; + if(typeof global !== "undefined"){ env = global } + if(typeof require !== "undefined"){ var Gun = require('../gun') } + if(typeof window !== "undefined"){ var Gun = (env = window).Gun } + + Gun.on('opt', function(at){ + this.to.next(at); + if(at.once){ return } + var root = at.gun; + root.on('in', function(at){ + if(!at.NTS){ + return this.to.next(at); + } + if(at['@']){ + (ask[at['@']]||noop)(at); + return; + } + if(env.window){ + return this.to.next(at); + } + this.to.next({'@': at['#'], NTS: Gun.time.is()}); }); - }; ping(); -}); -// You need to figure out how to make me write tests for this! -// maybe we can do human based testing where we load a HTML that just -// prints out in BIG FONT the objectiveTime it thinks it is -// and we open it up on a couple devices. \ No newline at end of file + + var ask = {}, noop = function(){}; + if(!env.window){ return } + + Gun.state.drift = Gun.state.drift || 0; + function ping(){ + var NTS = {}, ack = Gun.text.random(), msg = {'#': ack, NTS: true, gun: root}; + NTS.start = Gun.state(); + ask[ack] = function(at){ + NTS.end = Gun.state(); + Gun.obj.del(ask, ack); + NTS.latency = (NTS.end - NTS.start)/2; + if(!at.NTS){ return } + NTS.calc = NTS.latency + at.NTS; + Gun.state.drift -= (NTS.end - NTS.calc)/2; + setTimeout(ping, 1000); + } + Gun.on('out', msg); + }; ping(); + }); + // test by opening up examples/game/nts.html on devices that aren't NTP synced. +}()); \ No newline at end of file diff --git a/lib/serve.js b/lib/serve.js index ce6c9757..190261cd 100644 --- a/lib/serve.js +++ b/lib/serve.js @@ -7,5 +7,14 @@ module.exports = function serve(req, res, next){ res.end(serve.js = serve.js || require('fs').readFileSync(__dirname + '/../gun.js')); return true; } + if(0 <= req.url.indexOf('gun/')){ + res.writeHead(200, {'Content-Type': 'text/javascript'}); + var path = __dirname + '/../' + req.url.split('/').slice(2).join('/'), file; + try{file = require('fs').readFileSync(path)}catch(e){} + if(file){ + res.end(file); + return true; + } + } return next(); } \ No newline at end of file diff --git a/lib/server.js b/lib/server.js index 4fb9bd49..9f174b8c 100644 --- a/lib/server.js +++ b/lib/server.js @@ -1,6 +1,7 @@ ;(function(){ var Gun = require('../gun'); Gun.serve = require('./serve'); + require('./nts'); require('./s3'); try{require('./uws');}catch(e){require('./wsp/server');} require('./file'); diff --git a/package.json b/package.json index d85cbf35..c7354958 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gun", - "version": "0.6.7", + "version": "0.6.8", "description": "Graph engine", "main": "index.js", "browser": "gun.min.js",