From 186e4b14fe2466785870ce592a99893fc6be5d4b Mon Sep 17 00:00:00 2001 From: yflory Date: Mon, 10 Dec 2018 11:58:34 +0100 Subject: [PATCH] Add missing file --- www/pad/cursor.js | 154 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 www/pad/cursor.js diff --git a/www/pad/cursor.js b/www/pad/cursor.js new file mode 100644 index 000000000..ea3d7760c --- /dev/null +++ b/www/pad/cursor.js @@ -0,0 +1,154 @@ +define([ + 'jquery', + '/common/common-ui-elements.js', + '/common/common-interface.js', + '/bower_components/chainpad/chainpad.dist.js', +], function ($, UIElements, UI, ChainPad) { + var Cursor = {}; + + Cursor.isCursor = function (el) { + return typeof (el.getAttribute) === "function" && + el.getAttribute('class') && + /cp-cursor-position/.test(el.getAttribute('class')); + }; + + Cursor.preDiffApply = function (info) { + if (info.node && info.node.tagName === 'SPAN' && + info.node.getAttribute('class') && + /cp-cursor-position/.test(info.node.getAttribute('class'))) { + if (info.diff.action === 'removeElement') { + console.error('PREVENTING REMOVAL OF CURSOR', info.node); + return true; + } + } + }; + + Cursor.create = function (inner, hjsonToDom, cursorModule) { + var exp = {}; + + var cursors = {}; + + var makeTippy = function (cursor) { + /*var html = ''; + if (cursor.avatar && UIElements.getAvatar(cursor.avatar)) { + html += UIElements.getAvatar(cursor.avatar); + } + html += cursor.name + ''; + return html;*/ + return cursor.name; + }; + + var makeCursor = function (id, cursor) { + if (cursors[id]) { + cursors[id].el.remove(); + cursors[id].elstart.remove(); + cursors[id].elend.remove(); + } + cursors[id] = { + el: $('', { + 'id': id, + 'data-type': '', + title: makeTippy(cursor), + 'class': 'cp-cursor-position' + })[0], + elstart: $('', { + 'id': id, + 'data-type': 'start', + title: makeTippy(cursor), + 'class': 'cp-cursor-position' + })[0], + elend: $('', { + 'id': id, + 'data-type': 'end', + title: makeTippy(cursor), + 'class': 'cp-cursor-position' + })[0], + }; + return cursors[id]; + }; + var deleteCursor = function (id) { + if (!cursors[id]) { return; } + cursors[id].el.remove(); + cursors[id].elstart.remove(); + cursors[id].elend.remove(); + delete cursors[id]; + }; + + + var addCursorAtRange = function (cursorEl, r, cursor, type) { + var pos = type || 'start'; + var p = r[pos].el.parentNode; + var el = cursorEl['el'+type]; + if (cursor.color) { + $(el).css('border-color', cursor.color); + $(el).css('background-color', cursor.color); + } + if (r[pos].offset === 0) { + if (r[pos].el.nodeType === r[pos].el.TEXT_NODE) { + // Text node, insert at the beginning + p.insertBefore(el, p.childNodes[0] || null); + } else { + // Other node, insert as first child + r[pos].el.insertBefore(el, r[pos].el.childNodes[0] || null); + } + } else { + if (r[pos].el.nodeType !== r[pos].el.TEXT_NODE) { return; } + // Text node, we have to split... + var newNode = r[pos].el.splitText(r[pos].offset); + p.insertBefore(el, newNode); + } + }; + + exp.removeCursors = function () { + for (var id in cursors) { + deleteCursor(id); + } + }; + + exp.cursorGetter = function (hjson) { + cursorModule.offsetUpdate(); + var userDocStateDom = hjsonToDom(hjson); + var ops = ChainPad.Diff.diff(inner.outerHTML, userDocStateDom.outerHTML); + return cursorModule.getNewOffset(ops); + }; + + exp.onCursorUpdate = function (data, hjson) { + if (data.leave) { + if (data.id.length === 32) { + Object.keys(cursors).forEach(function (id) { + if (id.indexOf(data.id) === 0) { deleteCursor(id); } + }); + } + deleteCursor(data.id); + return; + } + var id = data.id; + var cursorObj = data.cursor; + + if (!cursorObj.selectionStart) { return; } + + // 1. Transform the cursor to get the offset relative to our doc + // 2. Turn it into a range + var userDocStateDom = hjsonToDom(hjson); + var ops = ChainPad.Diff.diff(userDocStateDom.outerHTML, inner.outerHTML); + var r = cursorModule.getNewRange({ + start: cursorObj.selectionStart, + end: cursorObj.selectionEnd + }, ops); + var cursorEl = makeCursor(id, cursorObj); + if (r.start.el === r.end.el && r.start.offset === r.end.offset) { + // Cursor + addCursorAtRange(cursorEl, r, cursorObj, ''); + } else { + // Selection + addCursorAtRange(cursorEl, r, cursorObj, 'end'); + addCursorAtRange(cursorEl, r, cursorObj, 'start'); + } + inner.normalize(); + }; + + return exp; + }; + + return Cursor; +});