Fossil SCM

Enable side by side editing and preview. While automatic updating of the preview 'pane'. Tested with Chrome and Firefox under Linux. Only Chrome works.

renez 2012-04-29 05:05 side-by-side-edit
Commit 20362c85a832af48310cd7edd0a5b3af9c87a834
1 file changed +168 -10
+168 -10
--- src/wiki.c
+++ src/wiki.c
@@ -258,10 +258,11 @@
258258
Blob wiki;
259259
Manifest *pWiki = 0;
260260
const char *zPageName;
261261
char *zHtmlPageName;
262262
int n;
263
+ int ss;
263264
const char *z;
264265
char *zBody = (char*)P("w");
265266
266267
if( zBody ){
267268
zBody = mprintf("%s", zBody);
@@ -336,36 +337,193 @@
336337
if( zBody==0 ){
337338
zBody = mprintf("<i>Empty Page</i>");
338339
}
339340
zHtmlPageName = mprintf("Edit: %s", zPageName);
340341
style_header(zHtmlPageName);
341
- if( P("preview")!=0 ){
342
+ ss = 0;
343
+ if(P("ss")) ss = atoi(P("ss"));
344
+ if( P("ssb")!=0 ){
345
+ ss= ss ? 0 : 1;
346
+ }
347
+ if(ss){
342348
blob_zero(&wiki);
343349
blob_append(&wiki, zBody, -1);
344
- @ Preview:<hr />
345
- wiki_convert(&wiki, 0, 0);
346
- @ <hr />
347
- blob_reset(&wiki);
350
+ } else {
351
+ if( P("preview")!=0 ){
352
+ blob_zero(&wiki);
353
+ blob_append(&wiki, zBody, -1);
354
+ @ Preview:<hr />
355
+ wiki_convert(&wiki, 0, 0);
356
+ @ <hr />
357
+ blob_reset(&wiki);
358
+ }
348359
}
349360
for(n=2, z=zBody; z[0]; z++){
350361
if( z[0]=='\n' ) n++;
351362
}
352363
if( n<20 ) n = 20;
353364
if( n>40 ) n = 40;
354
- @ <form method="post" action="%s(g.zTop)/wikiedit"><div>
365
+
366
+ if(ss){
367
+ @ <div id="twocolumns" style="width: 100%%;overflow:hidden">
368
+ @ <div id="colright" style="display:block;float:right;width:50%%;">
369
+ @ <div><h3>Preview</h3></div><div id="previewdiv">
370
+ wiki_convert(&wiki, 0, 0);
371
+ blob_reset(&wiki);
372
+ @ </div></div>
373
+ @ <div id="colleft" style="width:50%%;">
374
+ }
375
+ @ <form method="POST" action="%s(g.zTop)/wikiedit">
355376
login_insert_csrf_secret();
356377
@ <input type="hidden" name="name" value="%h(zPageName)" />
357
- @ <textarea name="w" class="wikiedit" cols="80"
358
- @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
378
+ @ <div> <input type="submit" id="ssb" name="ssb" value="Toggle Side-by-side" />
379
+ @ </div><input type="hidden" name="ss" value="%d(ss)" />
380
+ @ <textarea id="w" name="w" class="wikiedit" cols="70" rows="40"
381
+ @ >%h(zBody)</textarea>
359382
@ <br />
360
- @ <input type="submit" name="preview" value="Preview Your Changes" />
383
+ if(!ss){
384
+ @ <input type="submit" name="preview" value="Preview Your Changes" />
385
+ }
361386
@ <input type="submit" name="submit" value="Apply These Changes" />
362387
@ <input type="submit" name="cancel" value="Cancel" />
363
- @ </div></form>
388
+ @ </form>
389
+ if(ss){
390
+ @ </div>
391
+ @ <script type='text/javascript'>
392
+ @ function ajax(u,a,cb,errcb){
393
+ @ var _url = u;
394
+ @ var _method ='POST';
395
+ @ var _async = a;
396
+ @ var _userCallback = cb ;
397
+ @ var _defError = function(s,t){ alert('Ajax err('+s+') : '+t);} ;
398
+ @ var _errorCallback = errcb === undefined ? _defError : errcb;
399
+ @
400
+ @ var _starting;
401
+ @ var _request = false;
402
+ @ var _debug = false;
403
+ @ var _busy = function(){
404
+ @ return (0 < _request.readyState && 4 > _request.readyState);
405
+ @ }
406
+ @
407
+ @ if (window.XMLHttpRequest){ // Non-IE browsers
408
+ @ _request = new XMLHttpRequest();
409
+ @ } else if (window.ActiveXObject) { // IE
410
+ @ try {
411
+ @ _request = new ActiveXObject("Msxml2.XMLHTTP");
412
+ @ } catch(e) {
413
+ @ try {
414
+ @ _request = new ActiveXObject("Microsoft.XMLHTTP");
415
+ @ } catch(E) {
416
+ @ _request = false;
417
+ @ }
418
+ @ }
419
+ @ } else {
420
+ @ _request = false;
421
+ @ _errrorCallback(-1,'Ajax not available!');
422
+ @ }
423
+ @ var _callback =function(){
424
+ @ if(4 == _request.readyState){
425
+ @ if(200 == _request.status) {
426
+ @ if(_debug){
427
+ @ var _ending = new Date();
428
+ @ var sec = (_ending.getTime() - _starting.getTime())/1000;
429
+ @ alert(sec+" seconds. Callback with text\n "+_request.responseText);
430
+ @ }
431
+ @ _userCallback(_request.responseText,_request.responseXML);
432
+ @ } else {
433
+ @ _errorCallback(_request.status,_request.status);
434
+ @ }
435
+ @ }
436
+ @ }
437
+ @ this.abort = function(){ if(_busy()) {_request.abort(); } }
438
+ @ this.setDebug = function(onOff){ _debug = onOff;}
439
+ @ this.setMethod = function(onOff){ _method = onOff ? 'POST' : 'GET' ; }
440
+ @ this.setUrl = function(u){ _url = u; }
441
+ @ this.setAsync = function(onOff){ _async = onOff; }
442
+ @ this.send = function(data){
443
+ @ if(_debug) alert("in send function\nurl: "+_url
444
+ @ +"\nmethode "+_method
445
+ @ +"\nAsync "+_async
446
+ @ //+"\ndata "+data
447
+ @ );
448
+ @ if(_busy()){
449
+ @ if(_debug) alert('call in progress');
450
+ @ return 1;
451
+ @ }
452
+ @ try {
453
+ @ _starting = new Date();
454
+ @ _request.open(_method,_url,_async)
455
+ @ if(_async)
456
+ @ _request.onreadystatechange = _callback;
457
+ @ _request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
458
+ @ _request.send(data);
459
+ @ if(!_async){
460
+ @ _callback();
461
+ @ return _request.status;
462
+ @ }
463
+ @ } catch (e) {
464
+ @ _request.abort();
465
+ @ }
466
+ @ }
467
+ @ }
468
+ @ x = new ajax("%s(g.zTop)/wikipreview",true,cb)
469
+ @ //x.setDebug(true)
470
+ @
471
+ @ var sto = 10000
472
+ @ window.ta = document.getElementById('w')
473
+ @ window.ta.onkeydown= changed;
474
+ @ window.onload = pageLoaded
475
+ @ window.prvw = document.getElementById('previewdiv')
476
+ @ window.isChanged
477
+ @ function cb(text,xml){
478
+ @ window.prvw.innerHTML = text;
479
+ @ return true;
480
+ @ }
481
+ @ function preview(){
482
+ @ if(window.isChanged){
483
+ @ window.isChanged =0
484
+ @ x.send("w="+encodeURIComponent(window.ta.value))
485
+ @ }
486
+ @ setTimeout(preview,sto)
487
+ @ }
488
+ @ function pageLoaded(e){
489
+ @ window.isChanged =0
490
+ @ setTimeout(preview,sto)
491
+ @ }
492
+ @ function changed(e){
493
+ @ window.isChanged++
494
+ @ return true
495
+ @ }
496
+ @ </script>
497
+ }
364498
manifest_destroy(pWiki);
365499
style_footer();
366500
}
501
+
502
+/*
503
+** WEBPAGE: wikipreview
504
+** URL: /wikipreview
505
+**
506
+** render the contents of w
507
+** for use with Ajax. This is NOT
508
+** a complete web-page!
509
+*/
510
+void wikipreview_page(void){
511
+ Blob wiki;
512
+ char *zBody = (char*)P("w");
513
+ if( zBody ){
514
+ zBody = mprintf("%s", zBody);
515
+ }
516
+ login_check_credentials();
517
+ if( zBody==0 ){
518
+ zBody = mprintf("<i>Empty Page</i>");
519
+ }
520
+ blob_zero(&wiki);
521
+ blob_append(&wiki, zBody, -1);
522
+ wiki_convert(&wiki, 0, 0);
523
+ blob_reset(&wiki);
524
+}
367525
368526
/*
369527
** WEBPAGE: wikinew
370528
** URL /wikinew
371529
**
372530
--- src/wiki.c
+++ src/wiki.c
@@ -258,10 +258,11 @@
258 Blob wiki;
259 Manifest *pWiki = 0;
260 const char *zPageName;
261 char *zHtmlPageName;
262 int n;
 
263 const char *z;
264 char *zBody = (char*)P("w");
265
266 if( zBody ){
267 zBody = mprintf("%s", zBody);
@@ -336,36 +337,193 @@
336 if( zBody==0 ){
337 zBody = mprintf("<i>Empty Page</i>");
338 }
339 zHtmlPageName = mprintf("Edit: %s", zPageName);
340 style_header(zHtmlPageName);
341 if( P("preview")!=0 ){
 
 
 
 
 
342 blob_zero(&wiki);
343 blob_append(&wiki, zBody, -1);
344 @ Preview:<hr />
345 wiki_convert(&wiki, 0, 0);
346 @ <hr />
347 blob_reset(&wiki);
 
 
 
 
 
348 }
349 for(n=2, z=zBody; z[0]; z++){
350 if( z[0]=='\n' ) n++;
351 }
352 if( n<20 ) n = 20;
353 if( n>40 ) n = 40;
354 @ <form method="post" action="%s(g.zTop)/wikiedit"><div>
 
 
 
 
 
 
 
 
 
 
355 login_insert_csrf_secret();
356 @ <input type="hidden" name="name" value="%h(zPageName)" />
357 @ <textarea name="w" class="wikiedit" cols="80"
358 @ rows="%d(n)" wrap="virtual">%h(zBody)</textarea>
 
 
359 @ <br />
360 @ <input type="submit" name="preview" value="Preview Your Changes" />
 
 
361 @ <input type="submit" name="submit" value="Apply These Changes" />
362 @ <input type="submit" name="cancel" value="Cancel" />
363 @ </div></form>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364 manifest_destroy(pWiki);
365 style_footer();
366 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
367
368 /*
369 ** WEBPAGE: wikinew
370 ** URL /wikinew
371 **
372
--- src/wiki.c
+++ src/wiki.c
@@ -258,10 +258,11 @@
258 Blob wiki;
259 Manifest *pWiki = 0;
260 const char *zPageName;
261 char *zHtmlPageName;
262 int n;
263 int ss;
264 const char *z;
265 char *zBody = (char*)P("w");
266
267 if( zBody ){
268 zBody = mprintf("%s", zBody);
@@ -336,36 +337,193 @@
337 if( zBody==0 ){
338 zBody = mprintf("<i>Empty Page</i>");
339 }
340 zHtmlPageName = mprintf("Edit: %s", zPageName);
341 style_header(zHtmlPageName);
342 ss = 0;
343 if(P("ss")) ss = atoi(P("ss"));
344 if( P("ssb")!=0 ){
345 ss= ss ? 0 : 1;
346 }
347 if(ss){
348 blob_zero(&wiki);
349 blob_append(&wiki, zBody, -1);
350 } else {
351 if( P("preview")!=0 ){
352 blob_zero(&wiki);
353 blob_append(&wiki, zBody, -1);
354 @ Preview:<hr />
355 wiki_convert(&wiki, 0, 0);
356 @ <hr />
357 blob_reset(&wiki);
358 }
359 }
360 for(n=2, z=zBody; z[0]; z++){
361 if( z[0]=='\n' ) n++;
362 }
363 if( n<20 ) n = 20;
364 if( n>40 ) n = 40;
365
366 if(ss){
367 @ <div id="twocolumns" style="width: 100%%;overflow:hidden">
368 @ <div id="colright" style="display:block;float:right;width:50%%;">
369 @ <div><h3>Preview</h3></div><div id="previewdiv">
370 wiki_convert(&wiki, 0, 0);
371 blob_reset(&wiki);
372 @ </div></div>
373 @ <div id="colleft" style="width:50%%;">
374 }
375 @ <form method="POST" action="%s(g.zTop)/wikiedit">
376 login_insert_csrf_secret();
377 @ <input type="hidden" name="name" value="%h(zPageName)" />
378 @ <div> <input type="submit" id="ssb" name="ssb" value="Toggle Side-by-side" />
379 @ </div><input type="hidden" name="ss" value="%d(ss)" />
380 @ <textarea id="w" name="w" class="wikiedit" cols="70" rows="40"
381 @ >%h(zBody)</textarea>
382 @ <br />
383 if(!ss){
384 @ <input type="submit" name="preview" value="Preview Your Changes" />
385 }
386 @ <input type="submit" name="submit" value="Apply These Changes" />
387 @ <input type="submit" name="cancel" value="Cancel" />
388 @ </form>
389 if(ss){
390 @ </div>
391 @ <script type='text/javascript'>
392 @ function ajax(u,a,cb,errcb){
393 @ var _url = u;
394 @ var _method ='POST';
395 @ var _async = a;
396 @ var _userCallback = cb ;
397 @ var _defError = function(s,t){ alert('Ajax err('+s+') : '+t);} ;
398 @ var _errorCallback = errcb === undefined ? _defError : errcb;
399 @
400 @ var _starting;
401 @ var _request = false;
402 @ var _debug = false;
403 @ var _busy = function(){
404 @ return (0 < _request.readyState && 4 > _request.readyState);
405 @ }
406 @
407 @ if (window.XMLHttpRequest){ // Non-IE browsers
408 @ _request = new XMLHttpRequest();
409 @ } else if (window.ActiveXObject) { // IE
410 @ try {
411 @ _request = new ActiveXObject("Msxml2.XMLHTTP");
412 @ } catch(e) {
413 @ try {
414 @ _request = new ActiveXObject("Microsoft.XMLHTTP");
415 @ } catch(E) {
416 @ _request = false;
417 @ }
418 @ }
419 @ } else {
420 @ _request = false;
421 @ _errrorCallback(-1,'Ajax not available!');
422 @ }
423 @ var _callback =function(){
424 @ if(4 == _request.readyState){
425 @ if(200 == _request.status) {
426 @ if(_debug){
427 @ var _ending = new Date();
428 @ var sec = (_ending.getTime() - _starting.getTime())/1000;
429 @ alert(sec+" seconds. Callback with text\n "+_request.responseText);
430 @ }
431 @ _userCallback(_request.responseText,_request.responseXML);
432 @ } else {
433 @ _errorCallback(_request.status,_request.status);
434 @ }
435 @ }
436 @ }
437 @ this.abort = function(){ if(_busy()) {_request.abort(); } }
438 @ this.setDebug = function(onOff){ _debug = onOff;}
439 @ this.setMethod = function(onOff){ _method = onOff ? 'POST' : 'GET' ; }
440 @ this.setUrl = function(u){ _url = u; }
441 @ this.setAsync = function(onOff){ _async = onOff; }
442 @ this.send = function(data){
443 @ if(_debug) alert("in send function\nurl: "+_url
444 @ +"\nmethode "+_method
445 @ +"\nAsync "+_async
446 @ //+"\ndata "+data
447 @ );
448 @ if(_busy()){
449 @ if(_debug) alert('call in progress');
450 @ return 1;
451 @ }
452 @ try {
453 @ _starting = new Date();
454 @ _request.open(_method,_url,_async)
455 @ if(_async)
456 @ _request.onreadystatechange = _callback;
457 @ _request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
458 @ _request.send(data);
459 @ if(!_async){
460 @ _callback();
461 @ return _request.status;
462 @ }
463 @ } catch (e) {
464 @ _request.abort();
465 @ }
466 @ }
467 @ }
468 @ x = new ajax("%s(g.zTop)/wikipreview",true,cb)
469 @ //x.setDebug(true)
470 @
471 @ var sto = 10000
472 @ window.ta = document.getElementById('w')
473 @ window.ta.onkeydown= changed;
474 @ window.onload = pageLoaded
475 @ window.prvw = document.getElementById('previewdiv')
476 @ window.isChanged
477 @ function cb(text,xml){
478 @ window.prvw.innerHTML = text;
479 @ return true;
480 @ }
481 @ function preview(){
482 @ if(window.isChanged){
483 @ window.isChanged =0
484 @ x.send("w="+encodeURIComponent(window.ta.value))
485 @ }
486 @ setTimeout(preview,sto)
487 @ }
488 @ function pageLoaded(e){
489 @ window.isChanged =0
490 @ setTimeout(preview,sto)
491 @ }
492 @ function changed(e){
493 @ window.isChanged++
494 @ return true
495 @ }
496 @ </script>
497 }
498 manifest_destroy(pWiki);
499 style_footer();
500 }
501
502 /*
503 ** WEBPAGE: wikipreview
504 ** URL: /wikipreview
505 **
506 ** render the contents of w
507 ** for use with Ajax. This is NOT
508 ** a complete web-page!
509 */
510 void wikipreview_page(void){
511 Blob wiki;
512 char *zBody = (char*)P("w");
513 if( zBody ){
514 zBody = mprintf("%s", zBody);
515 }
516 login_check_credentials();
517 if( zBody==0 ){
518 zBody = mprintf("<i>Empty Page</i>");
519 }
520 blob_zero(&wiki);
521 blob_append(&wiki, zBody, -1);
522 wiki_convert(&wiki, 0, 0);
523 blob_reset(&wiki);
524 }
525
526 /*
527 ** WEBPAGE: wikinew
528 ** URL /wikinew
529 **
530

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button