@ -3,22 +3,24 @@ define([
'/common/messages.js' ,
'/common/messages.js' ,
'/common/crypto.js' ,
'/common/crypto.js' ,
'/_socket/realtime-input.js' ,
'/_socket/realtime-input.js' ,
'/common/convert.js' ,
'/common/hyperjson.js' ,
'/common/hyperscript.js' ,
'/_socket/toolbar.js' ,
'/_socket/toolbar.js' ,
'/common/cursor.js' ,
'/common/cursor.js' ,
'/common/json-ot.js' ,
'/common/json-ot.js' ,
'/_socket/typingTest.js' ,
'/bower_components/diff-dom/diffDOM.js' ,
'/bower_components/diff-dom/diffDOM.js' ,
'/bower_components/jquery/dist/jquery.min.js' ,
'/bower_components/jquery/dist/jquery.min.js' ,
'/customize/pad.js'
'/customize/pad.js'
] , function ( Config , Messages , Crypto , realtimeInput , Conver t, Toolbar , Cursor , JsonOT ) {
] , function ( Config , Messages , Crypto , realtimeInput , Hyperjson, Hyperscrip t, Toolbar , Cursor , JsonOT , TypingTest ) {
var $ = window . jQuery ;
var $ = window . jQuery ;
var ifrw = $ ( '#pad-iframe' ) [ 0 ] . contentWindow ;
var ifrw = $ ( '#pad-iframe' ) [ 0 ] . contentWindow ;
var Ckeditor ; // to be initialized later...
var Ckeditor ; // to be initialized later...
var DiffDom = window . diffDOM ;
var DiffDom = window . diffDOM ;
window . Convert = Convert ;
var hjsonToDom = function ( H ) {
return Hyperjson . callOn ( H , Hyperscript ) ;
window . Toolbar = Toolbar ;
} ;
var userName = Crypto . rand64 ( 8 ) ,
var userName = Crypto . rand64 ( 8 ) ,
toolbar ;
toolbar ;
@ -37,25 +39,6 @@ define([
return true ;
return true ;
} ;
} ;
var setRandomizedInterval = function ( func , target , range ) {
var timeout ;
var again = function ( ) {
timeout = setTimeout ( function ( ) {
again ( ) ;
func ( ) ;
} , target - ( range / 2 ) + Math . random ( ) * range ) ;
} ;
again ( ) ;
return {
cancel : function ( ) {
if ( timeout ) {
clearTimeout ( timeout ) ;
timeout = undefined ;
}
}
} ;
}
var andThen = function ( Ckeditor ) {
var andThen = function ( Ckeditor ) {
$ ( window ) . on ( 'hashchange' , function ( ) {
$ ( window ) . on ( 'hashchange' , function ( ) {
window . location . reload ( ) ;
window . location . reload ( ) ;
@ -87,10 +70,12 @@ define([
var inner = window . inner = documentBody ;
var inner = window . inner = documentBody ;
var cursor = window . cursor = Cursor ( inner ) ;
var cursor = window . cursor = Cursor ( inner ) ;
var $textarea = $ ( '#feedback' ) ;
var setEditable = function ( bool ) {
var setEditable = function ( bool ) {
inner . style . backgroundColor = bool ? 'unset' : 'grey' ;
// 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 ) ;
inner . setAttribute ( 'contenteditable' , bool ) ;
} ;
} ;
@ -148,42 +133,44 @@ define([
}
}
} ;
} ;
var initializing = true ;
var now = function ( ) { return new Date ( ) . getTime ( ) } ;
var assertStateMatches = function ( ) {
var realtimeOptions = {
var userDocState = module . realtimeInput . realtime . getUserDoc ( ) ;
// configuration :D
var currentState = $textarea . val ( ) ;
doc : inner ,
if ( currentState !== userDocState ) {
console . log ( {
userDocState : userDocState ,
currentState : currentState
} ) ;
throw new Error ( "currentState !== userDocState" ) ;
}
} ;
var updateDebugTextarea = function ( shjson ) {
// provide initialstate...
window . setTimeout ( function ( ) {
initialState : JSON . stringify ( Hyperjson . fromDOM ( inner , isNotMagicLine ) ) ,
$textarea . val ( shjson ) ;
} , 0 ) ;
} ;
var now = function ( ) { return new Date ( ) . getTime ( ) } ;
// really basic operational transform
// reject patch if it results in invalid JSON
transformFunction : JsonOT . validate ,
websocketURL : Config . websocketURL ,
// username
userName : userName ,
// communication channel name
channel : key . channel ,
// encryption key
cryptKey : key . cryptKey
} ;
var DD = new DiffDom ( diffOptions ) ;
var DD = new DiffDom ( diffOptions ) ;
// apply patches, and try not to lose the cursor in the process!
// apply patches, and try not to lose the cursor in the process!
var applyHjson = function ( shjson ) {
var applyHjson = function ( shjson ) {
//setEditable(false);
var userDocStateDom = hjsonToDom ( JSON . parse ( shjson ) ) ;
var userDocStateDom = Convert . hjson . to . dom ( JSON . parse ( shjson ) ) ;
userDocStateDom . setAttribute ( "contenteditable" , "true" ) ; // lol wtf
userDocStateDom . setAttribute ( "contenteditable" , "true" ) ; // lol wtf
//assertStateMatches();
var patch = ( DD ) . diff ( inner , userDocStateDom ) ;
var patch = ( DD ) . diff ( inner , userDocStateDom ) ;
( DD ) . apply ( inner , patch ) ;
( DD ) . apply ( inner , patch ) ;
// push back to the textarea so we get a userDocState
//setEditable(true);
} ;
} ;
var onRemote = function ( info ) {
var initializing = true ;
var onRemote = realtimeOptions . onRemote = function ( info ) {
if ( initializing ) { return ; }
if ( initializing ) { return ; }
var shjson = info . realtime . getUserDoc ( ) ;
var shjson = info . realtime . getUserDoc ( ) ;
@ -193,21 +180,20 @@ define([
// build a dom from HJSON, diff, and patch the editor
// build a dom from HJSON, diff, and patch the editor
applyHjson ( shjson ) ;
applyHjson ( shjson ) ;
//updateDebugTextarea(shjson);
var shjson2 = JSON . stringify ( Convert. core . h yperjson. fromDOM ( inner ) ) ;
var shjson2 = JSON . stringify ( H yperjson. fromDOM ( inner ) ) ;
if ( shjson2 !== shjson ) {
if ( shjson2 !== shjson ) {
rti . patchText ( shjson2 ) ;
rti . patchText ( shjson2 ) ;
}
}
} ;
} ;
var onInit = function ( info ) {
var onInit = realtimeOptions . onInit = function ( info ) {
var $bar = $ ( '#pad-iframe' ) [ 0 ] . contentWindow . $ ( '#cke_1_toolbox' ) ;
var $bar = $ ( '#pad-iframe' ) [ 0 ] . contentWindow . $ ( '#cke_1_toolbox' ) ;
toolbar = info . realtime . toolbar = Toolbar . create ( $bar , userName , info . realtime ) ;
toolbar = info . realtime . toolbar = Toolbar . create ( $bar , userName , info . realtime ) ;
/* TODO handle disconnects and such*/
/* TODO handle disconnects and such*/
} ;
} ;
var onReady = function ( info ) {
var onReady = realtimeOptions . onReady = function ( info ) {
console . log ( "Unlocking editor" ) ;
console . log ( "Unlocking editor" ) ;
initializing = false ;
initializing = false ;
setEditable ( true ) ;
setEditable ( true ) ;
@ -217,7 +203,7 @@ define([
applyHjson ( shjson ) ;
applyHjson ( shjson ) ;
} ;
} ;
var onAbort = function ( info ) {
var onAbort = realtimeOptions . onAbort = function ( info ) {
console . log ( "Aborting the session!" ) ;
console . log ( "Aborting the session!" ) ;
// stop the user from continuing to edit
// stop the user from continuing to edit
// by setting the editable to false
// by setting the editable to false
@ -225,90 +211,19 @@ define([
toolbar . failed ( ) ;
toolbar . failed ( ) ;
} ;
} ;
var realtimeOptions = {
// configuration :D
doc : inner ,
// first thing called
onInit : onInit ,
onReady : onReady ,
// when remote changes occur
onRemote : onRemote ,
// handle aborts
onAbort : onAbort ,
// provide initialstate...
initialState : JSON . stringify ( Convert . core . hyperjson . fromDOM ( inner , isNotMagicLine ) ) ,
// really basic operational transform
// reject patch if it results in invalid JSON
transformFunction : JsonOT . validate ,
websocketURL : Config . websocketURL ,
// username
userName : userName ,
// communication channel name
channel : key . channel ,
// encryption key
cryptKey : key . cryptKey
} ;
var rti = module . realtimeInput = realtimeInput . start ( realtimeOptions ) ;
var rti = module . realtimeInput = realtimeInput . start ( realtimeOptions ) ;
// FIXME Spaghetti code. realtime-input needs access to this variable..
// FIXME Spaghetti code. realtime-input needs access to this variable..
var propogate = window . cryptpad _propogate = function ( ) {
var propogate = window . cryptpad _propogate = function ( ) {
var shjson = JSON . stringify ( Convert. core . h yperjson. fromDOM ( inner , isNotMagicLine ) ) ;
var shjson = JSON . stringify ( Hyperjson . fromDOM ( inner , isNotMagicLine ) ) ;
if ( ! rti . patchText ( shjson ) ) { return ; }
if ( ! rti . patchText ( shjson ) ) { return ; }
rti . onEvent ( shjson ) ;
rti . onEvent ( shjson ) ;
} ;
} ;
var testInput = function ( el , offset ) {
var i = 0 ,
j = offset ,
input = "The quick red fox jumps over the lazy brown dog. " ,
l = input . length ,
errors = 0 ,
max _errors = 15 ,
interval ;
var cancel = function ( ) {
if ( interval ) { interval . cancel ( ) ; }
} ;
interval = setRandomizedInterval ( function ( ) {
propogate ( ) ;
try {
el . replaceData ( j , 0 , input . charAt ( i ) ) ;
} catch ( err ) {
errors ++ ;
if ( errors >= max _errors ) {
console . log ( "Max error number exceeded" ) ;
cancel ( ) ;
}
console . error ( err ) ;
var next = document . createTextNode ( "-" ) ;
window . inner . appendChild ( next ) ;
el = next ;
j = - 1 ;
}
i = ( i + 1 ) % l ;
j ++ ;
} , 200 , 50 ) ;
return {
cancel : cancel
} ;
} ;
var easyTest = window . easyTest = function ( ) {
var easyTest = window . easyTest = function ( ) {
cursor . update ( ) ;
cursor . update ( ) ;
var start = cursor . Range . start ;
var start = cursor . Range . start ;
var test = testInput( start . el , start . offset ) ;
var test = TypingTest . testInput ( start . el , start . offset , propogate ) ;
propogate ( ) ;
propogate ( ) ;
return test ;
return test ;
} ;
} ;