Fossil SCM

Per request in forumpost/9fd5135acc, added intra-document links to each response which link back to the being-replied-to post within the same page (using an #anchor-tag), without reloading from the server.

stephan 2019-07-02 04:45 trunk
Commit 78721d4aa0fa51ee98107da408c89bfa9c5e140ef7086e309aa28e15b59950c0
1 file changed +52 -11
+52 -11
--- src/forum.c
+++ src/forum.c
@@ -283,15 +283,55 @@
283283
@ Trust user "%h(pPost->zUser)"
284284
@ so that future posts by "%h(pPost->zUser)" do not require moderation.
285285
@ </label>
286286
@ <input type="hidden" name="trustuser" value="%h(pPost->zUser)">
287287
}
288
+
289
+/*
290
+** If pPost->firt then this routine outputs an "in reply to" link to
291
+** the post being replied to, else this is a no-op.
292
+**
293
+** The generated link is a document-local reference to #post-ID, where
294
+** ID is the short-form UUID of the being-reponded-to post (the length
295
+** being determined by the %!S cgi_printf() flag).
296
+**
297
+** zPostName must be the name of the current post being displayed, as
298
+** it appears in the the URL. e.g. for /forumpost/abcddcba, zPostName
299
+** must be "abcddcba". This is required for building an absolute link
300
+** to work around the document having a BASE tag which breaks
301
+** intra-document links (which HTML treats like relative links, thus
302
+** applying the BASE HREF to them).
303
+**
304
+** zTMode must be the current thread display mode: "c"=chronological,
305
+** "h"=hierarchical. (Without that parameter on the URL, the browser
306
+** switches from chronological to hierarchical view when clicking an
307
+** intra-document link in the former mode.)
308
+*/
309
+static void forum_output_reply_link( const char *zPostName,
310
+ const char * zTMode,
311
+ const ForumEntry * pPost ){
312
+ if( pPost->firt ){
313
+ const ForumEntry *pIrt = pPost->pPrev;
314
+ while( pIrt && pIrt->fpid!=pPost->firt ) pIrt = pIrt->pPrev;
315
+ if( pIrt ){
316
+ cgi_printf("in reply to [<a "
317
+ "href=\"%R/%s/%s?t=%s#post-%!S\">"
318
+ "%S</a>]\n",
319
+ g.zPath, zPostName, zTMode, pIrt->zUuid,
320
+ pIrt->zUuid);
321
+ }
322
+ }
323
+}
288324
289325
/*
290326
** Display all posts in a forum thread in chronological order
327
+**
328
+** See forum_output_reply_link() for details of the zPostName
329
+** parameter.
291330
*/
292
-static void forum_display_chronological(int froot, int target){
331
+static void forum_display_chronological(int froot, int target,
332
+ const char *zPostName){
293333
ForumThread *pThread = forumthread_create(froot, 0);
294334
ForumEntry *p;
295335
int notAnon = login_is_individual();
296336
for(p=pThread->pFirst; p; p=p->pNext){
297337
char *zDate;
@@ -306,26 +346,21 @@
306346
}else if( p->pLeaf!=0 ){
307347
@ <div id="forum%d(p->fpid)" class="forumTime forumObs">
308348
}else{
309349
@ <div id="forum%d(p->fpid)" class="forumTime">
310350
}
351
+ @ <a name="post-%!S(p->zUuid)"></a>
311352
if( pPost->zThreadTitle ){
312353
@ <h1>%h(pPost->zThreadTitle)</h1>
313354
}
314355
zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
315356
@ <p>By %h(pPost->zUser) on %h(zDate) (%d(p->fpid))
316357
fossil_free(zDate);
317358
if( p->pEdit ){
318359
@ edit of %z(href("%R/forumpost/%S?t=c",p->pEdit->zUuid))%d(p->fprev)</a>
319360
}
320
- if( p->firt ){
321
- ForumEntry *pIrt = p->pPrev;
322
- while( pIrt && pIrt->fpid!=p->firt ) pIrt = pIrt->pPrev;
323
- if( pIrt ){
324
- @ reply to %z(href("%R/forumpost/%S?t=c",pIrt->zUuid))%d(p->firt)</a>
325
- }
326
- }
361
+ forum_output_reply_link( zPostName, "c", p );
327362
if( p->pLeaf ){
328363
@ updated by %z(href("%R/forumpost/%S?t=c",p->pLeaf->zUuid))\
329364
@ %d(p->pLeaf->fpid)</a>
330365
}
331366
if( g.perm.Debug ){
@@ -374,12 +409,16 @@
374409
forumthread_delete(pThread);
375410
}
376411
377412
/*
378413
** Display all messages in a forumthread with indentation.
414
+**
415
+** See forum_output_reply_link() for details of the zPostName
416
+** parameter.
379417
*/
380
-static int forum_display_hierarchical(int froot, int target){
418
+static int forum_display_hierarchical(int froot, int target,
419
+ const char * zPostName){
381420
ForumThread *pThread;
382421
ForumEntry *p;
383422
Manifest *pPost, *pOPost;
384423
int fpid;
385424
const char *zUuid;
@@ -406,10 +445,11 @@
406445
}else{
407446
fpid = p->fpid;
408447
zUuid = p->zUuid;
409448
pPost = pOPost;
410449
}
450
+ @ <a name="post-%!S(zUuid)"></a>
411451
zSel = p->fpid==target ? " forumSel" : "";
412452
if( p->nIndent==1 ){
413453
@ <div id='forum%d(fpid)' class='forumHierRoot%s(zSel)'>
414454
}else{
415455
@ <div id='forum%d(fpid)' class='forumHier%s(zSel)' \
@@ -425,10 +465,11 @@
425465
fossil_free(zDate);
426466
if( g.perm.Debug ){
427467
@ <span class="debug">\
428468
@ <a href="%R/artifact/%h(p->zUuid)">(%d(p->fpid))</a></span>
429469
}
470
+ forum_output_reply_link( zPostName, "h", p );
430471
if( p->pLeaf ){
431472
zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
432473
if( fossil_strcmp(pOPost->zUser,pPost->zUser)==0 ){
433474
@ and edited on %h(zDate)
434475
}else{
@@ -543,14 +584,14 @@
543584
zMode = "h";
544585
}
545586
}
546587
if( zMode[0]=='c' ){
547588
style_submenu_element("Hierarchical", "%R/%s/%s?t=h", g.zPath, zName);
548
- forum_display_chronological(froot, fpid);
589
+ forum_display_chronological(froot, fpid, zName);
549590
}else{
550591
style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName);
551
- forum_display_hierarchical(froot, fpid);
592
+ forum_display_hierarchical(froot, fpid, zName);
552593
}
553594
style_load_js("forum.js");
554595
style_footer();
555596
}
556597
557598
--- src/forum.c
+++ src/forum.c
@@ -283,15 +283,55 @@
283 @ Trust user "%h(pPost->zUser)"
284 @ so that future posts by "%h(pPost->zUser)" do not require moderation.
285 @ </label>
286 @ <input type="hidden" name="trustuser" value="%h(pPost->zUser)">
287 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
289 /*
290 ** Display all posts in a forum thread in chronological order
 
 
 
291 */
292 static void forum_display_chronological(int froot, int target){
 
293 ForumThread *pThread = forumthread_create(froot, 0);
294 ForumEntry *p;
295 int notAnon = login_is_individual();
296 for(p=pThread->pFirst; p; p=p->pNext){
297 char *zDate;
@@ -306,26 +346,21 @@
306 }else if( p->pLeaf!=0 ){
307 @ <div id="forum%d(p->fpid)" class="forumTime forumObs">
308 }else{
309 @ <div id="forum%d(p->fpid)" class="forumTime">
310 }
 
311 if( pPost->zThreadTitle ){
312 @ <h1>%h(pPost->zThreadTitle)</h1>
313 }
314 zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
315 @ <p>By %h(pPost->zUser) on %h(zDate) (%d(p->fpid))
316 fossil_free(zDate);
317 if( p->pEdit ){
318 @ edit of %z(href("%R/forumpost/%S?t=c",p->pEdit->zUuid))%d(p->fprev)</a>
319 }
320 if( p->firt ){
321 ForumEntry *pIrt = p->pPrev;
322 while( pIrt && pIrt->fpid!=p->firt ) pIrt = pIrt->pPrev;
323 if( pIrt ){
324 @ reply to %z(href("%R/forumpost/%S?t=c",pIrt->zUuid))%d(p->firt)</a>
325 }
326 }
327 if( p->pLeaf ){
328 @ updated by %z(href("%R/forumpost/%S?t=c",p->pLeaf->zUuid))\
329 @ %d(p->pLeaf->fpid)</a>
330 }
331 if( g.perm.Debug ){
@@ -374,12 +409,16 @@
374 forumthread_delete(pThread);
375 }
376
377 /*
378 ** Display all messages in a forumthread with indentation.
 
 
 
379 */
380 static int forum_display_hierarchical(int froot, int target){
 
381 ForumThread *pThread;
382 ForumEntry *p;
383 Manifest *pPost, *pOPost;
384 int fpid;
385 const char *zUuid;
@@ -406,10 +445,11 @@
406 }else{
407 fpid = p->fpid;
408 zUuid = p->zUuid;
409 pPost = pOPost;
410 }
 
411 zSel = p->fpid==target ? " forumSel" : "";
412 if( p->nIndent==1 ){
413 @ <div id='forum%d(fpid)' class='forumHierRoot%s(zSel)'>
414 }else{
415 @ <div id='forum%d(fpid)' class='forumHier%s(zSel)' \
@@ -425,10 +465,11 @@
425 fossil_free(zDate);
426 if( g.perm.Debug ){
427 @ <span class="debug">\
428 @ <a href="%R/artifact/%h(p->zUuid)">(%d(p->fpid))</a></span>
429 }
 
430 if( p->pLeaf ){
431 zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
432 if( fossil_strcmp(pOPost->zUser,pPost->zUser)==0 ){
433 @ and edited on %h(zDate)
434 }else{
@@ -543,14 +584,14 @@
543 zMode = "h";
544 }
545 }
546 if( zMode[0]=='c' ){
547 style_submenu_element("Hierarchical", "%R/%s/%s?t=h", g.zPath, zName);
548 forum_display_chronological(froot, fpid);
549 }else{
550 style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName);
551 forum_display_hierarchical(froot, fpid);
552 }
553 style_load_js("forum.js");
554 style_footer();
555 }
556
557
--- src/forum.c
+++ src/forum.c
@@ -283,15 +283,55 @@
283 @ Trust user "%h(pPost->zUser)"
284 @ so that future posts by "%h(pPost->zUser)" do not require moderation.
285 @ </label>
286 @ <input type="hidden" name="trustuser" value="%h(pPost->zUser)">
287 }
288
289 /*
290 ** If pPost->firt then this routine outputs an "in reply to" link to
291 ** the post being replied to, else this is a no-op.
292 **
293 ** The generated link is a document-local reference to #post-ID, where
294 ** ID is the short-form UUID of the being-reponded-to post (the length
295 ** being determined by the %!S cgi_printf() flag).
296 **
297 ** zPostName must be the name of the current post being displayed, as
298 ** it appears in the the URL. e.g. for /forumpost/abcddcba, zPostName
299 ** must be "abcddcba". This is required for building an absolute link
300 ** to work around the document having a BASE tag which breaks
301 ** intra-document links (which HTML treats like relative links, thus
302 ** applying the BASE HREF to them).
303 **
304 ** zTMode must be the current thread display mode: "c"=chronological,
305 ** "h"=hierarchical. (Without that parameter on the URL, the browser
306 ** switches from chronological to hierarchical view when clicking an
307 ** intra-document link in the former mode.)
308 */
309 static void forum_output_reply_link( const char *zPostName,
310 const char * zTMode,
311 const ForumEntry * pPost ){
312 if( pPost->firt ){
313 const ForumEntry *pIrt = pPost->pPrev;
314 while( pIrt && pIrt->fpid!=pPost->firt ) pIrt = pIrt->pPrev;
315 if( pIrt ){
316 cgi_printf("in reply to [<a "
317 "href=\"%R/%s/%s?t=%s#post-%!S\">"
318 "%S</a>]\n",
319 g.zPath, zPostName, zTMode, pIrt->zUuid,
320 pIrt->zUuid);
321 }
322 }
323 }
324
325 /*
326 ** Display all posts in a forum thread in chronological order
327 **
328 ** See forum_output_reply_link() for details of the zPostName
329 ** parameter.
330 */
331 static void forum_display_chronological(int froot, int target,
332 const char *zPostName){
333 ForumThread *pThread = forumthread_create(froot, 0);
334 ForumEntry *p;
335 int notAnon = login_is_individual();
336 for(p=pThread->pFirst; p; p=p->pNext){
337 char *zDate;
@@ -306,26 +346,21 @@
346 }else if( p->pLeaf!=0 ){
347 @ <div id="forum%d(p->fpid)" class="forumTime forumObs">
348 }else{
349 @ <div id="forum%d(p->fpid)" class="forumTime">
350 }
351 @ <a name="post-%!S(p->zUuid)"></a>
352 if( pPost->zThreadTitle ){
353 @ <h1>%h(pPost->zThreadTitle)</h1>
354 }
355 zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
356 @ <p>By %h(pPost->zUser) on %h(zDate) (%d(p->fpid))
357 fossil_free(zDate);
358 if( p->pEdit ){
359 @ edit of %z(href("%R/forumpost/%S?t=c",p->pEdit->zUuid))%d(p->fprev)</a>
360 }
361 forum_output_reply_link( zPostName, "c", p );
 
 
 
 
 
 
362 if( p->pLeaf ){
363 @ updated by %z(href("%R/forumpost/%S?t=c",p->pLeaf->zUuid))\
364 @ %d(p->pLeaf->fpid)</a>
365 }
366 if( g.perm.Debug ){
@@ -374,12 +409,16 @@
409 forumthread_delete(pThread);
410 }
411
412 /*
413 ** Display all messages in a forumthread with indentation.
414 **
415 ** See forum_output_reply_link() for details of the zPostName
416 ** parameter.
417 */
418 static int forum_display_hierarchical(int froot, int target,
419 const char * zPostName){
420 ForumThread *pThread;
421 ForumEntry *p;
422 Manifest *pPost, *pOPost;
423 int fpid;
424 const char *zUuid;
@@ -406,10 +445,11 @@
445 }else{
446 fpid = p->fpid;
447 zUuid = p->zUuid;
448 pPost = pOPost;
449 }
450 @ <a name="post-%!S(zUuid)"></a>
451 zSel = p->fpid==target ? " forumSel" : "";
452 if( p->nIndent==1 ){
453 @ <div id='forum%d(fpid)' class='forumHierRoot%s(zSel)'>
454 }else{
455 @ <div id='forum%d(fpid)' class='forumHier%s(zSel)' \
@@ -425,10 +465,11 @@
465 fossil_free(zDate);
466 if( g.perm.Debug ){
467 @ <span class="debug">\
468 @ <a href="%R/artifact/%h(p->zUuid)">(%d(p->fpid))</a></span>
469 }
470 forum_output_reply_link( zPostName, "h", p );
471 if( p->pLeaf ){
472 zDate = db_text(0, "SELECT datetime(%.17g)", pPost->rDate);
473 if( fossil_strcmp(pOPost->zUser,pPost->zUser)==0 ){
474 @ and edited on %h(zDate)
475 }else{
@@ -543,14 +584,14 @@
584 zMode = "h";
585 }
586 }
587 if( zMode[0]=='c' ){
588 style_submenu_element("Hierarchical", "%R/%s/%s?t=h", g.zPath, zName);
589 forum_display_chronological(froot, fpid, zName);
590 }else{
591 style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName);
592 forum_display_hierarchical(froot, fpid, zName);
593 }
594 style_load_js("forum.js");
595 style_footer();
596 }
597
598

Keyboard Shortcuts

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