diff --git a/www/common/realtime-input.js b/www/common/realtime-input.js index 9c9e36a7c..6807879fb 100644 --- a/www/common/realtime-input.js +++ b/www/common/realtime-input.js @@ -64,8 +64,11 @@ define([ var bindAllEvents = function (textarea, docBody, onEvent, unbind) { - // FIXME why docBody? - + /* + we use docBody for the purposes of CKEditor. + because otherwise special keybindings like ctrl-b and ctrl-i + would open bookmarks and info instead of applying bold/italic styles + */ docBody && bindEvents(docBody, ['textInput', 'keydown', 'keyup', 'select', 'cut', 'paste'], onEvent, @@ -133,17 +136,20 @@ define([ }; var start = module.exports.start = - function (textarea, websocketUrl, userName, channel, cryptKey, doc, onRemote) + function (textarea, websocketUrl, userName, channel, cryptKey, config) { + var passwd = 'y'; - console.log({ - textarea: textarea, - websocketUrl: websocketUrl, - userName: userName, - channel: channel, - cryptKey: cryptKey - }); + // make sure configuration is defined + config = config || {}; + + var doc = config.doc || null; + + // trying to deprecate onRemote, prefer loading it via the conf + onRemote = config.onRemote || onRemote; + + transformFunction = config.transformFunction || null; var socket = makeWebsocket(websocketUrl); // define this in case it gets called before the rest of our stuff is ready. @@ -156,12 +162,6 @@ define([ var $textarea = $(textarea); - var inputDisabled = function (cond) { - $textarea.attr("disabled", cond||false); - }; - - inputDisabled(false); - var bump = function () {}; socket.onOpen.push(function (evt) { @@ -176,24 +176,11 @@ define([ channel, $(textarea).val(), { - transformFunction: function (text, toTransform, transformBy) { - console.log({ - text: text, - toTransform: toTransform, - transformBy: transformBy - }); - - // returning **null** breaks out of the loop - // which transforms conflicting operations - // in theory this should prevent us from producing bad JSON - return null; - } + transformFunction: config.transformFunction }); onEvent = function () { if (isErrorState || initializing) { return; } -/* var currentDoc = $textarea.val(); - if (currentDoc !== realtime.getUserDoc()) { warn("currentDoc !== realtime.getUserDoc()"); } */ }; realtime.onUserListChange(function (userList) { @@ -202,14 +189,13 @@ define([ } // if we spot ourselves being added to the document, we'll switch // 'initializing' off because it means we're fully synced. - - // we should only see this happen once initializing = false; - debug("Done initializing:"); - debug("Userlist: ["+userList.join(",")+"]"); - /* TODO execute a callback here */ - inputDisabled(true); + // execute an onReady callback if one was supplied + // pass an object so we can extend this later + config.onReady && config.onReady({ + userList: userList + }); }); var whoami = new RegExp(userName.replace(/\/\+/g, function (c) { @@ -274,7 +260,6 @@ define([ var socketChecker = setInterval(function () { if (checkSocket(socket)) { warn("Socket disconnected!"); - inputDisabled(true); recoverableErrorCount += 1; @@ -284,7 +269,7 @@ define([ socketChecker && clearInterval(socketChecker); } } else { - inputDisabled(false); + // TODO } },200); @@ -296,7 +281,6 @@ define([ realtime.start(); debug('started'); - // this has three names :| bump = realtime.bumpSharejs; }); return { diff --git a/www/render/index.html b/www/render/index.html index 7b1794dd1..b463a5dac 100644 --- a/www/render/index.html +++ b/www/render/index.html @@ -34,9 +34,18 @@ code { font-family: monospace; } - /* TODO - bump up text size on mobile - */ + + /* bigger text size for difficult to read elements */ + blockquote, p, pre, code, li { + font-size: 20px; + } + + /* tables */ + table, thead, tbody, th, tr, td{ + border: 1pt solid #586e75; + background-color: #002b36; + padding: 15px; + } @@ -46,4 +55,3 @@ - diff --git a/www/render/main.js b/www/render/main.js index 6f1825262..ba19b32ea 100644 --- a/www/render/main.js +++ b/www/render/main.js @@ -28,7 +28,7 @@ define([ var key = Crypto.parseKey(window.location.hash.substring(1)); - var $textarea = $('textarea'), + var $textarea = $('textarea').first(), $target = $('#target'); window.$textarea = $textarea; @@ -107,18 +107,23 @@ define([ }, 450); }; - var rts = $textarea.toArray().map(function (e, i) { - var rt = Realtime.start(e, // window + var rts = Realtime.start($textarea[0], // window Config.websocketURL, // websocketUrl Crypto.rand64(8), // userName key.channel, // channel key.cryptKey, // cryptkey - null, // docBody - function (){ // onChange received - lazyDraw($textarea.val()); + { + // when remote editors do things... + onRemote: function () { + lazyDraw($textarea.val()); + }, + // when your editor is ready + onReady: function (info) { + info.userList && console.log("Userlist: [%s]", info.userList.join(',')); + console.log("Realtime is ready!"); + $textarea.trigger('keyup'); + } }); - return rt; - })[0]; $textarea.on('change keyup keydown', function () { redrawTimeout && clearTimeout(redrawTimeout); diff --git a/www/vdom/main.js b/www/vdom/main.js index 7d4670b9a..e74f0cf32 100644 --- a/www/vdom/main.js +++ b/www/vdom/main.js @@ -49,7 +49,14 @@ define([ var vdom1 = Convert.dom.to.vdom(inner); - var onChange = function (shjson) { + var applyHjson = function (shjson) { + // where is your cursor? + // TODO optimize this if it works + /* + var sel = editor.getSelection(); // { rev, document, root, isLocked, _ } + var element = sel.getStartElement(); + var ranges = sel.getRanges(); // [0] // {startContainer, startOffset, endContainer, endOffset, collapsed, document, root} + */ var authDoc = JSON.parse(shjson); var vdom2 = Convert.hjson.to.vdom(authDoc); var patches = Vdom.diff(vdom1, vdom2); @@ -57,15 +64,57 @@ define([ // try resyncing the dom? vdom1 = Convert.dom.to.vdom(inner); // vdom1 = vdom2; + +/* + // correct the cursor after doing dom stuff + sel.selectElement(element); + ranges[0].setStart(element.getFirst(), ranges[0].startOffset); // + ranges[0].setEnd(element.getFirst(), ranges[0].endOffset); + sel.selectRanges([ranges[0]]); +*/ + }; - window.rti = realtimeInput.start($textarea[0], - Config.websocketURL, - Crypto.rand64(8), - key.channel, - key.cryptKey, - inner, - onChange); + window.rti = realtimeInput.start($textarea[0], // synced element + Config.websocketURL, // websocketURL, ofc + Crypto.rand64(8), // userName + key.channel, // channelName + key.cryptKey, // key + { // configuration :D + doc: inner, + + onReady: function (info) { + applyHjson($textarea.val()); + $textarea.trigger('keyup'); + }, + + onRemote: applyHjson, + + transformFunction : function (text, toTransform, transformBy) { + /* FIXME + operational transform on json shouldn't be in all editors + just those transmitting/expecting JSON + */ + false && console.log({ + text: text, + toTransform: toTransform, + transformBy: transformBy + }); + + // returning **null** breaks out of the loop + // which transforms conflicting operations + // in theory this should prevent us from producing bad JSON + return null; + } + /* + FIXME NOT A REAL FUNCTION WONT WORK + transformFunction: function (state0str, toTransform, transformBy) { + var state1A = JSON.parse(Operation.apply(state0str, transformBy)); + var state1B = JSON.parse(Operation.apply(state0str, toTransform)); + var state0 = JSON.parse(state0str); + } + */ + }); $textarea.val(JSON.stringify(Convert.dom.to.hjson(inner)));