diff --git a/www/vdom/main.js b/www/vdom/main.js index 613104189..f8f13ce09 100644 --- a/www/vdom/main.js +++ b/www/vdom/main.js @@ -4,12 +4,17 @@ define([ '/common/crypto.js', '/common/realtime-input.js', '/common/convert.js', + '/common/toolbar.js', + '/common/cursor.js', '/bower_components/jquery/dist/jquery.min.js', '/customize/pad.js' -], function (Config, Messages, Crypto, realtimeInput, Convert) { +], function (Config, Messages, Crypto, realtimeInput, Convert, Toolbar, Cursor) { var $ = window.jQuery; var ifrw = $('#pad-iframe')[0].contentWindow; - var Ckeditor = ifrw.CKEDITOR; + window.Ckeditor = ifrw.CKEDITOR; + + var userName = Crypto.rand64(8), + toolbar; var Vdom = Convert.core.vdom, Hyperjson = Convert.core.hyperjson; @@ -27,7 +32,7 @@ define([ var fixThings = false; var key = Crypto.parseKey(window.location.hash.substring(1)); - var editor = Ckeditor.replace('editor1', { + window.editor = Ckeditor.replace('editor1', { // https://dev.ckeditor.com/ticket/10907 needsBrFiller: fixThings, needsNbspFiller: fixThings, @@ -37,106 +42,54 @@ define([ removePlugins: 'magicline,resize' }); - window.editor = editor; + editor.on('instanceReady', function () { editor.execCommand('maximize'); - ifrw.$('iframe')[0].contentDocument.body.innerHTML = Messages.initialState; + var documentBody = ifrw.$('iframe')[0].contentDocument.body; - var inner = ifrw.$('iframe')[0].contentDocument.body; - window.inner = inner; + documentBody.innerHTML = Messages.initialState; - var $textarea = $('#feedback'), - $problem = $('#problemo'); + var inner = documentBody; + window.inner = inner; + window.cursor = Cursor(Ckeditor, editor, inner); - var debug = function (info) { - $problem.text(JSON.stringify(info,null,2)); - }; + var $textarea = $('#feedback'); var vdom1 = Convert.dom.to.vdom(inner); - var cursor = { - startEl: null, - startOffset: 0, - endEl: null, - endOffset: 0 - }; - - var getCursor = function () { - // 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(); - - if (!ranges.length) { return; } - var range = ranges[0]; // {startContainer, startOffset, endContainer, endOffset, collapsed, document, root} - - cursor.startEl = range.startContainer; - cursor.startOffset = range.startOffset; - - cursor.endEl = range.endContainer; - cursor.endOffset = range.endOffset; - - debug(cursor); - }; - - window.rangeElements = {}; - - var setCursor = function () { - try { - var sel = editor.getSelection(); // { rev, document, root, isLocked, _ } - - // correct the cursor after doing dom stuff - // sel.selectElement(element); - var ranges = sel.getRanges(); - if (!ranges.length) { return; } - var range = ranges[0]; // {startContainer, startOffset, endContainer, endOffset, collapsed, document, root} - - range.setStart(cursor.startEl, cursor.startOffset); - range.setEnd(cursor.endEl, cursor.endOffset); - sel.selectRanges([range]); - /* FIXME TODO - This fails because the element that we're operating on - can stop existing because vdom determines that we should - get rid of it. if it doesn't exist anymore, we should - walk up the tree or something. Or just not try to - relocate the cursor. Default behaviour might be ok. - DONT FIGHT THE DOM - */ - } catch (err) { - console.log("junk cursor:"); - console.log(cursor); - debug(cursor); - console.error(err); - console.error(err.stack); - } - }; - var applyHjson = function (shjson) { + console.log("Applying HJSON"); // before integrating external changes, check in your own vdom1 = Convert.dom.to.vdom(inner); - - // remember where the cursor is - getCursor() - // the authoritative document is hyperjson, parse it var authDoc = JSON.parse(shjson); // use the authdoc to construct a second vdom var vdom2 = Convert.hjson.to.vdom(authDoc); // diff it against your version var patches = Vdom.diff(vdom1, vdom2); - // apply the resulting patches Vdom.patch(inner, patches); + }; + + var onRemote = function (shjson) { + // remember where the cursor is + cursor.update() + + applyHjson(shjson); + + cursor.find(); // put the cursor back where you left it - setCursor(); + cursor.replace(); + }; + + var onInit = function (info) { + // TODO initialize the toolbar }; window.rti = realtimeInput.start($textarea[0], // synced element Config.websocketURL, // websocketURL, ofc - Crypto.rand64(8), // userName + userName, // userName key.channel, // channelName key.cryptKey, // key { // configuration :D @@ -147,7 +100,8 @@ define([ $textarea.trigger('keyup'); }, - onRemote: applyHjson, + onRemote: onRemote, + onInit: onInit, transformFunction : function (text, toTransform, transformBy) { /* FIXME @@ -175,28 +129,22 @@ define([ */ }); - $(inner).on('keyup', function () { - getCursor(); - }); - $textarea.val(JSON.stringify(Convert.dom.to.hjson(inner))); editor.on('change', function () { var hjson = Hyperjson.fromDOM(inner); - /* - hjson = Hyperjson.callOn(hjson, function (a, b, c) { - Object.keys(b).forEach(function (k) { - if (a === "BR" && b[k] === '_moz') { - delete b[k]; - } - }); - return [a,b,c]; - });*/ $textarea.val(JSON.stringify(hjson)); rti.bumpSharejs(); - getCursor() + cursor.update() + }); + + ['mouseup', 'keyup'].forEach(function (type) { + editor.document.on(type, function (e) { + cursor.update(); + }); }); + }); };