start on a vdom-based wysiwyg realtime
There are still a few conditions that cause it to 'explode' when different browsers disagree on element semantics. Overall it's a much cleaner approach, but it will require extensive tuning to improve performance, as there are still many complete dom traversals which will not scale for large documents
This commit is contained in:
parent
1f7f90165f
commit
d14e42fedd
41
www/vdom/index.html
Normal file
41
www/vdom/index.html
Normal file
@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||
<script data-main="main" src="/bower_components/requirejs/require.js"></script>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
#pad-iframe {
|
||||
position:fixed;
|
||||
top:0px;
|
||||
left:0px;
|
||||
bottom:0px;
|
||||
right:0px;
|
||||
width:50%;
|
||||
height:100%;
|
||||
border:none;
|
||||
margin:0;
|
||||
padding:0;
|
||||
overflow:hidden;
|
||||
}
|
||||
#feedback {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
border: 0px;
|
||||
height: 100vh;
|
||||
width: 50vw;
|
||||
background-color: #222;
|
||||
color: #ccc;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="pad-iframe" src="inner.html"></iframe>
|
||||
<textarea id="feedback"></textarea>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
12
www/vdom/inner.html
Normal file
12
www/vdom/inner.html
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
|
||||
<script src="/bower_components/ckeditor/ckeditor.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<textarea style="display:none" id="editor1" name="editor1"></textarea>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
97
www/vdom/main.js
Normal file
97
www/vdom/main.js
Normal file
@ -0,0 +1,97 @@
|
||||
define([
|
||||
'/api/config?cb=' + Math.random().toString(16).substring(2),
|
||||
'/common/messages.js',
|
||||
'/common/crypto.js',
|
||||
'/common/realtime-input.js',
|
||||
'/common/convert.js',
|
||||
'/bower_components/jquery/dist/jquery.min.js',
|
||||
'/customize/pad.js'
|
||||
], function (Config, Messages, Crypto, realtimeInput, Convert) {
|
||||
var $ = window.jQuery;
|
||||
var ifrw = $('#pad-iframe')[0].contentWindow;
|
||||
var Ckeditor = ifrw.CKEDITOR;
|
||||
|
||||
var Vdom = Convert.core.vdom,
|
||||
Hyperjson = Convert.core.hyperjson;
|
||||
|
||||
window.Hyperjson = Hyperjson;
|
||||
|
||||
var andThen = function () {
|
||||
$(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 = 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
|
||||
removePlugins: 'magicline,resize'
|
||||
});
|
||||
|
||||
window.editor = editor;
|
||||
editor.on('instanceReady', function () {
|
||||
editor.execCommand('maximize');
|
||||
ifrw.$('iframe')[0].contentDocument.body.innerHTML = Messages.initialState;
|
||||
|
||||
var inner = ifrw.$('iframe')[0].contentDocument.body;
|
||||
window.inner = inner;
|
||||
|
||||
var $textarea = $('#feedback');
|
||||
|
||||
var vdom1 = Convert.dom.to.vdom(inner);
|
||||
|
||||
window.rti = realtimeInput.start($textarea[0],
|
||||
Config.websocketURL,
|
||||
Crypto.rand64(8),
|
||||
key.channel,
|
||||
key.cryptKey,
|
||||
inner,
|
||||
function (shjson) {
|
||||
var authDoc = JSON.parse(shjson);
|
||||
var vdom2 = Convert.hjson.to.vdom(authDoc);
|
||||
var patches = Vdom.diff(vdom1, vdom2);
|
||||
Vdom.patch(inner, patches);
|
||||
vdom1 = vdom2;
|
||||
});
|
||||
|
||||
$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();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var interval = 100;
|
||||
var first = function () {
|
||||
if (Ckeditor = ifrw.CKEDITOR) {
|
||||
andThen();
|
||||
} else {
|
||||
console.log("Ckeditor was not defined. Trying again in %sms",interval);
|
||||
setTimeout(first, interval);
|
||||
}
|
||||
};
|
||||
|
||||
$(first);
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user