clean up realtime-input.js, break API
use an object for configuration, so as to be more extensible. modify applications which use the API to match.
This commit is contained in:
parent
e43b9715e8
commit
d96124229b
@ -64,8 +64,11 @@ define([
|
|||||||
|
|
||||||
var bindAllEvents = function (textarea, docBody, onEvent, unbind)
|
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,
|
docBody && bindEvents(docBody,
|
||||||
['textInput', 'keydown', 'keyup', 'select', 'cut', 'paste'],
|
['textInput', 'keydown', 'keyup', 'select', 'cut', 'paste'],
|
||||||
onEvent,
|
onEvent,
|
||||||
@ -133,17 +136,20 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
var start = module.exports.start =
|
var start = module.exports.start =
|
||||||
function (textarea, websocketUrl, userName, channel, cryptKey, doc, onRemote)
|
function (textarea, websocketUrl, userName, channel, cryptKey, config)
|
||||||
{
|
{
|
||||||
|
|
||||||
var passwd = 'y';
|
var passwd = 'y';
|
||||||
|
|
||||||
console.log({
|
// make sure configuration is defined
|
||||||
textarea: textarea,
|
config = config || {};
|
||||||
websocketUrl: websocketUrl,
|
|
||||||
userName: userName,
|
var doc = config.doc || null;
|
||||||
channel: channel,
|
|
||||||
cryptKey: cryptKey
|
// trying to deprecate onRemote, prefer loading it via the conf
|
||||||
});
|
onRemote = config.onRemote || onRemote;
|
||||||
|
|
||||||
|
transformFunction = config.transformFunction || null;
|
||||||
|
|
||||||
var socket = makeWebsocket(websocketUrl);
|
var socket = makeWebsocket(websocketUrl);
|
||||||
// define this in case it gets called before the rest of our stuff is ready.
|
// define this in case it gets called before the rest of our stuff is ready.
|
||||||
@ -156,12 +162,6 @@ define([
|
|||||||
|
|
||||||
var $textarea = $(textarea);
|
var $textarea = $(textarea);
|
||||||
|
|
||||||
var inputDisabled = function (cond) {
|
|
||||||
$textarea.attr("disabled", cond||false);
|
|
||||||
};
|
|
||||||
|
|
||||||
inputDisabled(false);
|
|
||||||
|
|
||||||
var bump = function () {};
|
var bump = function () {};
|
||||||
|
|
||||||
socket.onOpen.push(function (evt) {
|
socket.onOpen.push(function (evt) {
|
||||||
@ -176,24 +176,11 @@ define([
|
|||||||
channel,
|
channel,
|
||||||
$(textarea).val(),
|
$(textarea).val(),
|
||||||
{
|
{
|
||||||
transformFunction: function (text, toTransform, transformBy) {
|
transformFunction: config.transformFunction
|
||||||
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;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onEvent = function () {
|
onEvent = function () {
|
||||||
if (isErrorState || initializing) { return; }
|
if (isErrorState || initializing) { return; }
|
||||||
/* var currentDoc = $textarea.val();
|
|
||||||
if (currentDoc !== realtime.getUserDoc()) { warn("currentDoc !== realtime.getUserDoc()"); } */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
realtime.onUserListChange(function (userList) {
|
realtime.onUserListChange(function (userList) {
|
||||||
@ -202,14 +189,13 @@ define([
|
|||||||
}
|
}
|
||||||
// if we spot ourselves being added to the document, we'll switch
|
// if we spot ourselves being added to the document, we'll switch
|
||||||
// 'initializing' off because it means we're fully synced.
|
// 'initializing' off because it means we're fully synced.
|
||||||
|
|
||||||
// we should only see this happen once
|
|
||||||
initializing = false;
|
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) {
|
var whoami = new RegExp(userName.replace(/\/\+/g, function (c) {
|
||||||
@ -274,7 +260,6 @@ define([
|
|||||||
var socketChecker = setInterval(function () {
|
var socketChecker = setInterval(function () {
|
||||||
if (checkSocket(socket)) {
|
if (checkSocket(socket)) {
|
||||||
warn("Socket disconnected!");
|
warn("Socket disconnected!");
|
||||||
inputDisabled(true);
|
|
||||||
|
|
||||||
recoverableErrorCount += 1;
|
recoverableErrorCount += 1;
|
||||||
|
|
||||||
@ -284,7 +269,7 @@ define([
|
|||||||
socketChecker && clearInterval(socketChecker);
|
socketChecker && clearInterval(socketChecker);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
inputDisabled(false);
|
// TODO
|
||||||
}
|
}
|
||||||
},200);
|
},200);
|
||||||
|
|
||||||
@ -296,7 +281,6 @@ define([
|
|||||||
realtime.start();
|
realtime.start();
|
||||||
debug('started');
|
debug('started');
|
||||||
|
|
||||||
// this has three names :|
|
|
||||||
bump = realtime.bumpSharejs;
|
bump = realtime.bumpSharejs;
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -34,9 +34,18 @@
|
|||||||
code {
|
code {
|
||||||
font-family: monospace;
|
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;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -46,4 +55,3 @@
|
|||||||
<textarea></textarea>
|
<textarea></textarea>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ define([
|
|||||||
|
|
||||||
var key = Crypto.parseKey(window.location.hash.substring(1));
|
var key = Crypto.parseKey(window.location.hash.substring(1));
|
||||||
|
|
||||||
var $textarea = $('textarea'),
|
var $textarea = $('textarea').first(),
|
||||||
$target = $('#target');
|
$target = $('#target');
|
||||||
|
|
||||||
window.$textarea = $textarea;
|
window.$textarea = $textarea;
|
||||||
@ -107,18 +107,23 @@ define([
|
|||||||
}, 450);
|
}, 450);
|
||||||
};
|
};
|
||||||
|
|
||||||
var rts = $textarea.toArray().map(function (e, i) {
|
var rts = Realtime.start($textarea[0], // window
|
||||||
var rt = Realtime.start(e, // window
|
|
||||||
Config.websocketURL, // websocketUrl
|
Config.websocketURL, // websocketUrl
|
||||||
Crypto.rand64(8), // userName
|
Crypto.rand64(8), // userName
|
||||||
key.channel, // channel
|
key.channel, // channel
|
||||||
key.cryptKey, // cryptkey
|
key.cryptKey, // cryptkey
|
||||||
null, // docBody
|
{
|
||||||
function (){ // onChange received
|
// when remote editors do things...
|
||||||
|
onRemote: function () {
|
||||||
lazyDraw($textarea.val());
|
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 () {
|
$textarea.on('change keyup keydown', function () {
|
||||||
redrawTimeout && clearTimeout(redrawTimeout);
|
redrawTimeout && clearTimeout(redrawTimeout);
|
||||||
|
|||||||
@ -49,7 +49,14 @@ define([
|
|||||||
|
|
||||||
var vdom1 = Convert.dom.to.vdom(inner);
|
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 authDoc = JSON.parse(shjson);
|
||||||
var vdom2 = Convert.hjson.to.vdom(authDoc);
|
var vdom2 = Convert.hjson.to.vdom(authDoc);
|
||||||
var patches = Vdom.diff(vdom1, vdom2);
|
var patches = Vdom.diff(vdom1, vdom2);
|
||||||
@ -57,15 +64,57 @@ define([
|
|||||||
// try resyncing the dom?
|
// try resyncing the dom?
|
||||||
vdom1 = Convert.dom.to.vdom(inner);
|
vdom1 = Convert.dom.to.vdom(inner);
|
||||||
// vdom1 = vdom2;
|
// 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],
|
window.rti = realtimeInput.start($textarea[0], // synced element
|
||||||
Config.websocketURL,
|
Config.websocketURL, // websocketURL, ofc
|
||||||
Crypto.rand64(8),
|
Crypto.rand64(8), // userName
|
||||||
key.channel,
|
key.channel, // channelName
|
||||||
key.cryptKey,
|
key.cryptKey, // key
|
||||||
inner,
|
{ // configuration :D
|
||||||
onChange);
|
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)));
|
$textarea.val(JSON.stringify(Convert.dom.to.hjson(inner)));
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user