diff --git a/www/p/index.html b/www/p/index.html deleted file mode 100644 index 830d56125..000000000 --- a/www/p/index.html +++ /dev/null @@ -1,30 +0,0 @@ - - -
- - - - - - - - - diff --git a/www/p/inner.html b/www/p/inner.html deleted file mode 100644 index bf79dcd0d..000000000 --- a/www/p/inner.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/www/p/main.js b/www/p/main.js deleted file mode 100644 index 64eda9f70..000000000 --- a/www/p/main.js +++ /dev/null @@ -1,359 +0,0 @@ -require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/JSON.sortify' } }); -define([ - '/api/config?cb=' + Math.random().toString(16).substring(2), - '/common/messages.js', - '/common/crypto.js', - '/common/RealtimeTextSocket.js', - '/common/hyperjson.js', - '/common/hyperscript.js', - '/p/toolbar.js', - '/common/cursor.js', - '/common/json-ot.js', - '/common/TypingTests.js', - 'json.sortify', - '/common/TextPatcher.js', - '/bower_components/diff-dom/diffDOM.js', - '/bower_components/jquery/dist/jquery.min.js', - '/customize/pad.js' -], function (Config, Messages, Crypto, realtimeInput, Hyperjson, Hyperscript, Toolbar, Cursor, JsonOT, TypingTest, JSONSortify, TextPatcher) { - var $ = window.jQuery; - var ifrw = $('#pad-iframe')[0].contentWindow; - var Ckeditor; // to be initialized later... - var DiffDom = window.diffDOM; - - var stringify = function (obj) { - return JSONSortify(obj); - }; - - window.Hyperjson = Hyperjson; - - var hjsonToDom = function (H) { - return Hyperjson.callOn(H, Hyperscript); - }; - - var userName = Crypto.rand64(8), - toolbar; - - var module = window.REALTIME_MODULE = { - Hyperjson: Hyperjson, - Hyperscript: Hyperscript, - logFights: true, - fights: [], - }; - - var isNotMagicLine = function (el) { - // factor as: - // return !(el.tagName === 'SPAN' && el.contentEditable === 'false'); - var filter = (el.tagName === 'SPAN' && - el.getAttribute('contentEditable') === 'false'); - if (filter) { - console.log("[hyperjson.serializer] prevented an element" + - "from being serialized:", el); - return false; - } - return true; - }; - - /* catch `type="_moz"` before it goes over the wire */ - var brFilter = function (hj) { - if (hj[1].type === '_moz') { hj[1].type = undefined; } - return hj; - }; - - /* TODO integrate into flow to prevent browser fights over style */ - var setStyle = function (elem, newStyleAttr) { - elem.setAttribute("data-chainpad-origstyle", newStyleAttr); - elem.setAttribute("style", newStyleAttr); - elem.setAttribute("data-chainpad-styleclone", elem.getAttribute("style")); - }; - - /* TODO integrate into flow to prevent browser fights over style */ - var getStyle = function (elem) { - var st = elem.getAttribute("style"); - if (elem.getAttribute("data-chainpad-styleclone") !== st) { return st; } - return elem.getAttribute("data-chainpad-origstyle"); - }; - - var stringifyDOM = module.stringifyDOM = function (dom) { - return stringify(Hyperjson.fromDOM(dom, isNotMagicLine, brFilter)); - }; - - var andThen = function (Ckeditor) { - $(window).on('hashchange', function() { - window.location.reload(); - }); - if (window.location.href.indexOf('#') === -1) { - window.location.href = window.location.href + '#' + Crypto.genKey(); - return; - } - - var fixThings = false; - var key = Crypto.parseKey(window.location.hash.substring(1)); - var editor = window.editor = Ckeditor.replace('editor1', { - // https://dev.ckeditor.com/ticket/10907 - needsBrFiller: fixThings, - needsNbspFiller: fixThings, - removeButtons: 'Source,Maximize', - // magicline plugin inserts html crap into the document which is not part of the - // document itself and causes problems when it's sent across the wire and reflected back - // but we filter it now, so that's ok. - removePlugins: 'resize' - }); - - editor.on('instanceReady', function (Ckeditor) { - editor.execCommand('maximize'); - var documentBody = ifrw.$('iframe')[0].contentDocument.body; - - documentBody.innerHTML = Messages.initialState; - - var inner = window.inner = documentBody; - var cursor = window.cursor = Cursor(inner); - - var setEditable = function (bool) { - // careful about putting attributes onto the DOM - // they get put into the chain, and you can have trouble - // getting rid of them later - - //inner.style.backgroundColor = bool? 'white': 'grey'; - inner.setAttribute('contenteditable', bool); - }; - - // don't let the user edit until the pad is ready - setEditable(false); - - var diffOptions = { - preDiffApply: function (info) { - /* DiffDOM will filter out magicline plugin elements - in practice this will make it impossible to use it - while someone else is typing, which could be annoying. - - we should check when such an element is going to be - removed, and prevent that from happening. */ - if (info.node && info.node.tagName === 'SPAN' && - info.node.getAttribute('contentEditable') === "false") { - // it seems to be a magicline plugin element... - if (info.diff.action === 'removeElement') { - // and you're about to remove it... - // this probably isn't what you want - - /* - I have never seen this in the console, but the - magic line is still getting removed on remote - edits. This suggests that it's getting removed - by something other than diffDom. - */ - console.log("preventing removal of the magic line!"); - - // return true to prevent diff application - return true; - } - } - - // no use trying to recover the cursor if it doesn't exist - if (!cursor.exists()) { return; } - - /* frame is either 0, 1, 2, or 3, depending on which - cursor frames were affected: none, first, last, or both - */ - var frame = info.frame = cursor.inNode(info.node); - - if (!frame) { return; } - - if (typeof info.diff.oldValue === 'string' && typeof info.diff.newValue === 'string') { - var pushes = cursor.pushDelta(info.diff.oldValue, info.diff.newValue); - - if (frame & 1) { - // push cursor start if necessary - if (pushes.commonStart < cursor.Range.start.offset) { - cursor.Range.start.offset += pushes.delta; - } - } - if (frame & 2) { - // push cursor end if necessary - if (pushes.commonStart < cursor.Range.end.offset) { - cursor.Range.end.offset += pushes.delta; - } - } - } - }, - postDiffApply: function (info) { - if (info.frame) { - if (info.node) { - if (info.frame & 1) { cursor.fixStart(info.node); } - if (info.frame & 2) { cursor.fixEnd(info.node); } - } else { console.error("info.node did not exist"); } - - var sel = cursor.makeSelection(); - var range = cursor.makeRange(); - - cursor.fixSelection(sel, range); - } - } - }; - - var now = function () { return new Date().getTime(); }; - - var realtimeOptions = { - // provide initialstate... - initialState: stringifyDOM(inner) || '{}', - - // really basic operational transform - // reject patch if it results in invalid JSON - transformFunction : JsonOT.validate, - - websocketURL: Config.websocketURL+'_old', - - // username - userName: userName, - - // communication channel name - channel: key.channel, - - // encryption key - cryptKey: key.cryptKey, - - crypto: Crypto, - }; - - var DD = new DiffDom(diffOptions); - - // apply patches, and try not to lose the cursor in the process! - var applyHjson = function (shjson) { - var userDocStateDom = hjsonToDom(JSON.parse(shjson)); - - /* in the DOM contentEditable is "false" - while "contenteditable" is undefined. - - When it goes over the wire, it seems hyperjson transforms it. - of course, hyperjson simply gets attributes from the DOM. - - el.attributes returns 'contenteditable', so we have to correct for that - - There are quite possibly all sorts of other attributes which might lose - information, and we won't know what they are until after we've lost them. - - this comes from hyperscript line 101. FIXME maybe - */ - userDocStateDom.setAttribute("contenteditable", "true"); // lol wtf - var patch = (DD).diff(inner, userDocStateDom); - (DD).apply(inner, patch); - }; - - var initializing = true; - - var onRemote = realtimeOptions.onRemote = function (info) { - if (initializing) { return; } - - var shjson = info.realtime.getUserDoc(); - - // remember where the cursor is - cursor.update(); - - // build a dom from HJSON, diff, and patch the editor - applyHjson(shjson); - - var shjson2 = stringifyDOM(inner); - if (shjson2 !== shjson) { - /* the client's browser made changes when pushing content - into the dom */ - console.error("shjson2 !== shjson"); - // push those changes back over the wire - module.patchText(shjson2); - - /* pushing back over the wire is necessary, but it can - result in a feedback loop, which we call a browser - fight */ - if (module.logFights) { - // what changed? - var op = TextPatcher.diff(shjson, shjson2); - // log the changes - TextPatcher.log(shjson, op); - var sop = JSON.stringify(TextPatcher.format(shjson, op)); - - var index = module.fights.indexOf(sop); - if (index === -1) { - module.fights.push(sop); - console.log("Found a new type of browser disagreement"); - console.log("You can inspect the list in your " + - "console at `REALTIME_MODULE.fights`"); - console.log(module.fights); - } else { - console.log("Encountered a known browser disagreement: " + - "available at `REALTIME_MODULE.fights[%s]`", index); - } - } - } - }; - - var onInit = realtimeOptions.onInit = function (info) { - var $bar = $('#pad-iframe')[0].contentWindow.$('#cke_1_toolbox'); - toolbar = info.realtime.toolbar = Toolbar.create($bar, userName, info.realtime); - - /* TODO handle disconnects and such*/ - }; - - var onReady = realtimeOptions.onReady = function (info) { - var shjson = info.realtime.getUserDoc(); - - module.patchText = TextPatcher.create({ - realtime: info.realtime, - logging: true, - }); - - applyHjson(shjson); - console.log("Unlocking editor"); - setEditable(true); - initializing = false; - }; - - var onAbort = realtimeOptions.onAbort = function (info) { - console.log("Aborting the session!"); - // stop the user from continuing to edit - // by setting the editable to false - setEditable(false); - toolbar.failed(); - }; - - var onLocal = realtimeOptions.onLocal = function () { - if (initializing) { return; } - var shjson = stringifyDOM(inner); - module.patchText(shjson); - }; - - var rti = module.realtimeInput = realtimeInput.start(realtimeOptions); - - /* hitting enter makes a new line, but places the cursor inside - of the. This makes it such that you
- cannot type until you click, which is rather unnacceptable.
- If the cursor is ever inside such a
, you probably want
- to push it out to the parent element, which ought to be a
- paragraph tag. This needs to be done on keydown, otherwise
- the first such keypress will not be inserted into the P. */
- inner.addEventListener('keydown', cursor.brFix);
-
- var easyTest = window.easyTest = function () {
- cursor.update();
- var start = cursor.Range.start;
- var test = TypingTest.testInput(inner, start.el, start.offset, onLocal);
- // why twice?
- onLocal();
- return test;
- };
-
- editor.on('change', onLocal);
- });
- };
-
- var interval = 100;
- var first = function () {
- Ckeditor = ifrw.CKEDITOR;
- if (Ckeditor) {
- andThen(Ckeditor);
- } else {
- console.log("Ckeditor was not defined. Trying again in %sms",interval);
- setTimeout(first, interval);
- }
- };
-
- $(first);
-});
diff --git a/www/p/toolbar.js b/www/p/toolbar.js
deleted file mode 100644
index 4159ea0ac..000000000
--- a/www/p/toolbar.js
+++ /dev/null
@@ -1,233 +0,0 @@
-define([
- '/common/messages.js'
-], function (Messages) {
-
- /** Id of the element for getting debug info. */
- var DEBUG_LINK_CLS = 'rtwysiwyg-debug-link';
-
- /** Id of the div containing the user list. */
- var USER_LIST_CLS = 'rtwysiwyg-user-list';
-
- /** Id of the div containing the lag info. */
- var LAG_ELEM_CLS = 'rtwysiwyg-lag';
-
- /** The toolbar class which contains the user list, debug link and lag. */
- var TOOLBAR_CLS = 'rtwysiwyg-toolbar';
-
- /** Key in the localStore which indicates realtime activity should be disallowed. */
- var LOCALSTORAGE_DISALLOW = 'rtwysiwyg-disallow';
-
- var SPINNER_DISAPPEAR_TIME = 3000;
- var SPINNER = [ '-', '\\', '|', '/' ];
-
- var uid = function () {
- return 'rtwysiwyg-uid-' + String(Math.random()).substring(2);
- };
-
- var createRealtimeToolbar = function ($container) {
- var id = uid();
- $container.prepend(
- '