diff --git a/examples/docs.html b/examples/docs.html index 87412a8a..abc11b64 100644 --- a/examples/docs.html +++ b/examples/docs.html @@ -46,6 +46,8 @@ var gun = Gun('https://guntest.herokuapp.com/gun'); }); })(); +$("").css({position: 'fixed', height: '5em', width: '100%', bottom: 0, left: 0, 'font-size': '18pt'}).appendTo('body') + document.execCommand('defaultParagraphSeparator', false, 'p'); meta.edit({ name: "Edit", @@ -53,36 +55,65 @@ meta.edit({ use: function(eve){ console.log('on'); }, on: function(eve){ + var edit = this; meta.flip(false); - console.log('use'); - console.log("TRIGGERED!!!!???"); - //meta.tap.on.attr('contenteditable', 'true'); - $('#page').attr('contenteditable', 'true'); - $(document).on('keyup.tmp', '[contenteditable]', function(eve){ - if(eve.which != 13){ return true } - console.log(eve.which, $(this).text()); - return false; + var doc = $('#page').attr('contenteditable', 'true'); + if(!doc.text()){ + doc.html(''); + edit.select(doc.children().first().get(0)); + } + $(document).on('keydown.tmp', '[contenteditable]', function(eve){ + if(eve.which != 13){ return } + eve.preventDefault(); + var r = window.getSelection().getRangeAt(0); + var c = r.commonAncestorContainer; + r.deleteContents(); + c.splitText(r.startOffset); + var p = $(c).parent(), n = $("<"+p.get(0).tagName+">"), f; + p.contents().each(function(){ + if(this === c){ return f = true } + if(!f){ return } + n.append(this); + }); + p.after(n); + edit.select(n.get(0)); }).on('keyup.tmp', '[contenteditable]', function(eve){ - return; + $('#debug').val(doc.html()); var p = $(window.getSelection().anchorNode).closest('p'); var r = monotype(p); var html = p.html() || ''; var safe = $.normalize(html); - console.log("BEFORE:", html); - console.log("AFTER:", safe); p.html(safe); - r.restore() + r.restore(); }); }, up: function(){ console.log("UP"); $('[contenteditable=true]').off('.tmp'); + }, + select: function(p){ + var s = window.getSelection(), + r = document.createRange(); + if(p.innerHTML){ + r.setStart(p, 0); + r.collapse(true); + s.removeAllRanges(); + s.addRange(r); + return; + } + p.innerHTML = '\u00a0'; + r.selectNodeContents(p); + s.removeAllRanges(); + s.addRange(r); + document.execCommand('delete', false, null); } }); + meta.edit({ name: "Save", combo: ['S'], fake: -1, on: function(eve){ + return; meta.tap.on.attr('contenteditable', 'false'); var what = $.normalize($('#page').html()); var file = (location.hash||'').slice(1); diff --git a/lib/normalize.js b/lib/normalize.js index bac4214d..5f0859bd 100644 --- a/lib/normalize.js +++ b/lib/normalize.js @@ -1,7 +1,8 @@ (function(){ $.normalize = function(html, customOpt){ - var html, root$, wrapped, opt; + html = html || ''; + var root$, wrapped, opt; opt = html.opt || (customOpt ? prepareOptTags($.extend(true, baseOpt, customOpt)) : defaultOpt); if(!html.opt){ diff --git a/lib/stats.js b/lib/stats.js index 5e92afba..6ccf8105 100644 --- a/lib/stats.js +++ b/lib/stats.js @@ -5,6 +5,7 @@ Gun.on('opt', function(root){ if(root.once){ return } if(typeof process === 'undefined'){ return } if(typeof require === 'undefined'){ return } + if(false === root.opt.stats){ return } var noop = function(){}; var os = require('os') || {}; var fs = require('fs') || {}; diff --git a/test/panic/4dht.js b/test/panic/4dht.js new file mode 100644 index 00000000..996ec04c --- /dev/null +++ b/test/panic/4dht.js @@ -0,0 +1,136 @@ +/* +This is the first in a series of basic networking correctness tests. +Each test itself might be dumb and simple, but built up together, +they prove desired end goals for behavior at scale. +*/ + +var config = { + IP: require('ip').address(), + port: 8765, + servers: 2, + browsers: 2, + route: { + '/': __dirname + '/index.html', + '/gun.js': __dirname + '/../../gun.js', + '/jquery.js': __dirname + '/../../examples/jquery.js' + } +} + +var panic = require('panic-server'); +panic.server().on('request', function(req, res){ + config.route[req.url] && require('fs').createReadStream(config.route[req.url]).pipe(res); +}).listen(config.port); + +var clients = panic.clients; +var manager = require('panic-manager')(); + +manager.start({ + clients: Array(config.servers).fill().map(function(u, i){ + return { + type: 'node', + port: config.port + (i + 1) + } + }), + panic: 'http://' + config.IP + ':' + config.port +}); + +var servers = clients.filter('Node.js'); +var bob = servers.pluck(1); +var carl = servers.excluding(bob).pluck(1); +var browsers = clients.excluding(servers); +var alice = browsers.pluck(1); +var dave = browsers.excluding(alice).pluck(1); + +describe("Put ACK", function(){ + //this.timeout(5 * 60 * 1000); + this.timeout(10 * 60 * 1000); + + it("Servers have joined!", function(){ + return servers.atLeast(config.servers); + }); + + it("GUN started!", function(){ + var tests = [], i = 0; + servers.each(function(client){ + tests.push(client.run(function(test){ + var env = test.props; + test.async(); + try{ require('fs').unlinkSync(env.i+'data') }catch(e){} + try{ require('gun/lib/fsrm')(env.i+'data') }catch(e){} + var server = require('http').createServer(function(req, res){ + res.end("I am "+ env.i +"!"); + }); + var port = env.config.port + env.i; + var Gun = require('gun'); + var peers = [], i = env.config.servers; + while(i--){ + var tmp = (env.config.port + (i + 1)); + if(port != tmp){ // ignore ourselves + peers.push('http://'+ env.config.IP + ':' + tmp + '/gun'); + } + } + console.log(port, " connect to ", peers); + var gun = Gun({file: env.i+'data', peers: peers, web: server}); + server.listen(port, function(){ + test.done(); + }); + }, {i: i += 1, config: config})); + }); + return Promise.all(tests); + }); + + it(config.browsers +" browser(s) have joined!", function(){ + console.log("PLEASE OPEN http://"+ config.IP +":"+ config.port +" IN "+ config.browsers +" BROWSER(S)!"); + return browsers.atLeast(config.browsers); + }); + + it("Browsers initialized gun!", function(){ + var tests = [], i = 1; + browsers.each(function(client, id){ + tests.push(client.run(function(test){ + try{ localStorage.clear() }catch(e){} + try{ indexedDB.deleteDatabase('radata') }catch(e){} + var env = test.props; + var gun = Gun('http://'+ env.config.IP + ':' + (env.config.port + 1) + '/gun'); + window.gun = gun; + window.ref = gun.get('test'); + }, {i: i += 1, config: config})); + }); + return Promise.all(tests); + }); + + it("Alice", function(){ + return alice.run(function(test){ + console.log("I AM ALICE"); + //test.async(); + console.log(gun._.opt.peers); + }); + }); + + it("Dave", function(){ + return dave.run(function(test){ + console.log("I AM DAVE"); + //test.async(); + console.log(gun._.opt.peers); + }); + }); + + it("All finished!", function(done){ + console.log("Done! Cleaning things up..."); + setTimeout(function(){ + done(); + //},1000); + },1000 * 60); + }); + + after("Everything shut down.", function(){ + browsers.run(function(){ + //location.reload(); + //setTimeout(function(){ + //}, 15 * 1000); + }); + return servers.run(function(){ + process.exit(); + }); + }); +}); \ No newline at end of file diff --git a/test/panic/livestream.js b/test/panic/livestream.js index 41a87161..f9fe1c95 100644 --- a/test/panic/livestream.js +++ b/test/panic/livestream.js @@ -41,7 +41,7 @@ var servers = clients.filter('Node.js'); var bob = servers.pluck(1); var browsers = clients.excluding(servers); var alice = browsers.pluck(1); -var others = clients.excluding(alice); +var others = browsers.excluding(alice); describe("Broadcast Video", function(){ //this.timeout(5 * 60 * 1000); @@ -99,7 +99,11 @@ describe("Broadcast Video", function(){ } load('https://cdn.jsdelivr.net/gh/QVDev/GunStreamer/js/GunRecorder.js', function(){ load('https://cdn.jsdelivr.net/gh/QVDev/GunStreamer/js/GunStreamer.js', function(){ - test.done(); + load('https://cdn.jsdelivr.net/gh/QVDev/GunStreamer/js/GunViewer.js', function(){ + load('https://cdn.jsdelivr.net/gh/QVDev/GunStreamer/js/mediabuffer.js', function(){ + test.done(); + }); + }); }); }); $('body').append(''); @@ -136,21 +140,38 @@ describe("Broadcast Video", function(){ mimeType: 'video/webm; codecs="opus,vp8"', //audioBitsPerSecond: 6000,//Audio bits per second this is the lowest quality //videoBitsPerSecond: 100000,//Video bits per second this is the lowest quality - cameraOptions: {video:{width: 1280, height: 720, facingMode: "environment", frameRate: 60}, audio: true}, + cameraOptions: {video:{width: 1280, height: 720, facingMode: "environment", frameRate: 60}, audio: false}, video_id: "video", recordInterval: 1000, // how long each chunk? onRecordStateChange: function(state){ /* change play/pause buttons */ }, - onDataAvailable: function(data){ console.log('r -> s', data); stream.onDataAvailable(data) } // pass recorded data to streamer + onDataAvailable: function(data){ stream.onDataAvailable(data) } // pass recorded data to streamer }); record.startCamera(); $('#video').on('playing', function(eve){ - console.log("YES!!!"); record.record(); + test.done(); }); console.log("start recording!"); }, {acks: config.servers}); }); + it("View", function(){ + return others.run(function(test){ + console.log("I AM A VIEWER!"); + test.async(); + var view = new GunViewer({ + //mimeType: 'video/webm; codecs="opus,vp8"', // NEED THIS ONE FOR AUDIO+VIDEO + mimeType: 'video/webm; codecs="vp8"', + streamerId: "video", + debug: true,//For debug logs + }); + gun.get('livestream').on(function(data){ + window.data = data; + view.onStreamerData(data); + }); + }, {acks: config.servers}); + }); + it("All finished!", function(done){ console.log("Done! Cleaning things up..."); setTimeout(function(){