Fossil SCM

Clean up to the graph generator. Add comments describing variables in the javascript. Omit merge descenders if parent descenders are omitted. Add a test page of URL links.

drh 2010-12-30 20:37 trunk
Commit 94979bc7e3d34e8db7877c29a21199b4a116231f
+2 -1
--- src/config.h
+++ src/config.h
@@ -89,13 +89,14 @@
8989
*/
9090
typedef sqlite3_int64 i64;
9191
typedef sqlite3_uint64 u64;
9292
9393
/*
94
-** Unsigned character type
94
+** 8-bit types
9595
*/
9696
typedef unsigned char u8;
97
+typedef signed char i8;
9798
9899
/* In the timeline, check-in messages are truncated at the first space
99100
** that is more than MX_CKIN_MSG from the beginning, or at the first
100101
** paragraph break that is more than MN_CKIN_MSG from the beginning.
101102
*/
102103
--- src/config.h
+++ src/config.h
@@ -89,13 +89,14 @@
89 */
90 typedef sqlite3_int64 i64;
91 typedef sqlite3_uint64 u64;
92
93 /*
94 ** Unsigned character type
95 */
96 typedef unsigned char u8;
 
97
98 /* In the timeline, check-in messages are truncated at the first space
99 ** that is more than MX_CKIN_MSG from the beginning, or at the first
100 ** paragraph break that is more than MN_CKIN_MSG from the beginning.
101 */
102
--- src/config.h
+++ src/config.h
@@ -89,13 +89,14 @@
89 */
90 typedef sqlite3_int64 i64;
91 typedef sqlite3_uint64 u64;
92
93 /*
94 ** 8-bit types
95 */
96 typedef unsigned char u8;
97 typedef signed char i8;
98
99 /* In the timeline, check-in messages are truncated at the first space
100 ** that is more than MX_CKIN_MSG from the beginning, or at the first
101 ** paragraph break that is more than MN_CKIN_MSG from the beginning.
102 */
103
+29 -8
--- src/graph.c
+++ src/graph.c
@@ -31,11 +31,11 @@
3131
** the top-most row and increases moving down. Hence (in the absence of
3232
** time skew) parents have a larger index than their children.
3333
*/
3434
struct GraphRow {
3535
int rid; /* The rid for the check-in */
36
- int nParent; /* Number of parents */
36
+ i8 nParent; /* Number of parents */
3737
int aParent[GR_MAX_PARENT]; /* Array of parents. 0 element is primary .*/
3838
char *zBranch; /* Branch name */
3939
char *zBgClr; /* Background Color */
4040
4141
GraphRow *pNext; /* Next row down in the list of all rows */
@@ -43,19 +43,19 @@
4343
4444
int idx; /* Row index. First is 1. 0 used for "none" */
4545
int idxTop; /* Direct descendent highest up on the graph */
4646
GraphRow *pChild; /* Child immediately above this node */
4747
u8 isDup; /* True if this is duplicate of a prior entry */
48
- int iRail; /* Which rail this check-in appears on. 0-based.*/
49
- int aiRaiser[GR_MAX_RAIL]; /* Raisers from this node to a higher row. */
50
- int bDescender; /* Raiser from bottom of graph to here. */
48
+ u8 bDescender; /* True if riser from bottom of graph to here. */
49
+ i8 iRail; /* Which rail this check-in appears on. 0-based.*/
50
+ i8 mergeOut; /* Merge out to this rail */
51
+ int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */
5152
u32 mergeIn; /* Merge in from other rails */
52
- int mergeOut; /* Merge out to this rail */
5353
int mergeUpto; /* Draw the merge rail up to this level */
5454
u32 mergeDown; /* Draw merge lines up from bottom of graph */
5555
56
- u32 railInUse; /* Mask of occupied rails */
56
+ u32 railInUse; /* Mask of occupied rails at this row */
5757
};
5858
5959
/* Context while building a graph
6060
*/
6161
struct GraphContext {
@@ -242,11 +242,11 @@
242242
for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){
243243
assert( pPrior->idx > pCurrent->idx );
244244
assert( pCurrent->iRail<0 );
245245
pCurrent->iRail = iRail;
246246
pCurrent->railInUse |= mask;
247
- pPrior->aiRaiser[iRail] = pCurrent->idx;
247
+ pPrior->aiRiser[iRail] = pCurrent->idx;
248248
while( pPrior->idx > pCurrent->idx ){
249249
pPrior->railInUse |= mask;
250250
pPrior = pPrior->pPrev;
251251
assert( pPrior!=0 );
252252
}
@@ -279,10 +279,31 @@
279279
pDup->isDup = 1;
280280
}
281281
hashInsert(p, pRow, 1);
282282
}
283283
p->mxRail = -1;
284
+
285
+ /* Purge merge-parents that are out-of-graph if descenders are not
286
+ ** drawn.
287
+ **
288
+ ** Each node has one primary parent and zero or more "merge" parents.
289
+ ** A merge parent is a prior checkin from which changes were merged into
290
+ ** the current check-in. If a merge parent is not in the visible section
291
+ ** of this graph, then no arrows will be drawn for it, so remove it from
292
+ ** the aParent[] array.
293
+ */
294
+ if( omitDescenders ){
295
+ for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
296
+ for(i=1; i<pRow->nParent; i++){
297
+ if( hashFind(p, pRow->aParent[i])==0 ){
298
+ pRow->aParent[i] = pRow->aParent[--pRow->nParent];
299
+ i--;
300
+ }
301
+ }
302
+ }
303
+ }
304
+
284305
285306
/* Find the pChild pointer for each node.
286307
**
287308
** The pChild points to the node directly above on the same rail.
288309
** The pChild must be in the same branch. Leaf nodes have a NULL
@@ -360,11 +381,11 @@
360381
pRow->iRail = ++p->mxRail;
361382
pRow->railInUse = 1<<pRow->iRail;
362383
continue;
363384
}
364385
pRow->iRail = findFreeRail(p, 0, pParent->idx, inUse, pParent->iRail);
365
- pParent->aiRaiser[pRow->iRail] = pRow->idx;
386
+ pParent->aiRiser[pRow->iRail] = pRow->idx;
366387
}
367388
mask = 1<<pRow->iRail;
368389
pRow->railInUse |= mask;
369390
if( pRow->pChild==0 ){
370391
inUse &= ~mask;
371392
--- src/graph.c
+++ src/graph.c
@@ -31,11 +31,11 @@
31 ** the top-most row and increases moving down. Hence (in the absence of
32 ** time skew) parents have a larger index than their children.
33 */
34 struct GraphRow {
35 int rid; /* The rid for the check-in */
36 int nParent; /* Number of parents */
37 int aParent[GR_MAX_PARENT]; /* Array of parents. 0 element is primary .*/
38 char *zBranch; /* Branch name */
39 char *zBgClr; /* Background Color */
40
41 GraphRow *pNext; /* Next row down in the list of all rows */
@@ -43,19 +43,19 @@
43
44 int idx; /* Row index. First is 1. 0 used for "none" */
45 int idxTop; /* Direct descendent highest up on the graph */
46 GraphRow *pChild; /* Child immediately above this node */
47 u8 isDup; /* True if this is duplicate of a prior entry */
48 int iRail; /* Which rail this check-in appears on. 0-based.*/
49 int aiRaiser[GR_MAX_RAIL]; /* Raisers from this node to a higher row. */
50 int bDescender; /* Raiser from bottom of graph to here. */
 
51 u32 mergeIn; /* Merge in from other rails */
52 int mergeOut; /* Merge out to this rail */
53 int mergeUpto; /* Draw the merge rail up to this level */
54 u32 mergeDown; /* Draw merge lines up from bottom of graph */
55
56 u32 railInUse; /* Mask of occupied rails */
57 };
58
59 /* Context while building a graph
60 */
61 struct GraphContext {
@@ -242,11 +242,11 @@
242 for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){
243 assert( pPrior->idx > pCurrent->idx );
244 assert( pCurrent->iRail<0 );
245 pCurrent->iRail = iRail;
246 pCurrent->railInUse |= mask;
247 pPrior->aiRaiser[iRail] = pCurrent->idx;
248 while( pPrior->idx > pCurrent->idx ){
249 pPrior->railInUse |= mask;
250 pPrior = pPrior->pPrev;
251 assert( pPrior!=0 );
252 }
@@ -279,10 +279,31 @@
279 pDup->isDup = 1;
280 }
281 hashInsert(p, pRow, 1);
282 }
283 p->mxRail = -1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
285 /* Find the pChild pointer for each node.
286 **
287 ** The pChild points to the node directly above on the same rail.
288 ** The pChild must be in the same branch. Leaf nodes have a NULL
@@ -360,11 +381,11 @@
360 pRow->iRail = ++p->mxRail;
361 pRow->railInUse = 1<<pRow->iRail;
362 continue;
363 }
364 pRow->iRail = findFreeRail(p, 0, pParent->idx, inUse, pParent->iRail);
365 pParent->aiRaiser[pRow->iRail] = pRow->idx;
366 }
367 mask = 1<<pRow->iRail;
368 pRow->railInUse |= mask;
369 if( pRow->pChild==0 ){
370 inUse &= ~mask;
371
--- src/graph.c
+++ src/graph.c
@@ -31,11 +31,11 @@
31 ** the top-most row and increases moving down. Hence (in the absence of
32 ** time skew) parents have a larger index than their children.
33 */
34 struct GraphRow {
35 int rid; /* The rid for the check-in */
36 i8 nParent; /* Number of parents */
37 int aParent[GR_MAX_PARENT]; /* Array of parents. 0 element is primary .*/
38 char *zBranch; /* Branch name */
39 char *zBgClr; /* Background Color */
40
41 GraphRow *pNext; /* Next row down in the list of all rows */
@@ -43,19 +43,19 @@
43
44 int idx; /* Row index. First is 1. 0 used for "none" */
45 int idxTop; /* Direct descendent highest up on the graph */
46 GraphRow *pChild; /* Child immediately above this node */
47 u8 isDup; /* True if this is duplicate of a prior entry */
48 u8 bDescender; /* True if riser from bottom of graph to here. */
49 i8 iRail; /* Which rail this check-in appears on. 0-based.*/
50 i8 mergeOut; /* Merge out to this rail */
51 int aiRiser[GR_MAX_RAIL]; /* Risers from this node to a higher row. */
52 u32 mergeIn; /* Merge in from other rails */
 
53 int mergeUpto; /* Draw the merge rail up to this level */
54 u32 mergeDown; /* Draw merge lines up from bottom of graph */
55
56 u32 railInUse; /* Mask of occupied rails at this row */
57 };
58
59 /* Context while building a graph
60 */
61 struct GraphContext {
@@ -242,11 +242,11 @@
242 for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){
243 assert( pPrior->idx > pCurrent->idx );
244 assert( pCurrent->iRail<0 );
245 pCurrent->iRail = iRail;
246 pCurrent->railInUse |= mask;
247 pPrior->aiRiser[iRail] = pCurrent->idx;
248 while( pPrior->idx > pCurrent->idx ){
249 pPrior->railInUse |= mask;
250 pPrior = pPrior->pPrev;
251 assert( pPrior!=0 );
252 }
@@ -279,10 +279,31 @@
279 pDup->isDup = 1;
280 }
281 hashInsert(p, pRow, 1);
282 }
283 p->mxRail = -1;
284
285 /* Purge merge-parents that are out-of-graph if descenders are not
286 ** drawn.
287 **
288 ** Each node has one primary parent and zero or more "merge" parents.
289 ** A merge parent is a prior checkin from which changes were merged into
290 ** the current check-in. If a merge parent is not in the visible section
291 ** of this graph, then no arrows will be drawn for it, so remove it from
292 ** the aParent[] array.
293 */
294 if( omitDescenders ){
295 for(pRow=p->pFirst; pRow; pRow=pRow->pNext){
296 for(i=1; i<pRow->nParent; i++){
297 if( hashFind(p, pRow->aParent[i])==0 ){
298 pRow->aParent[i] = pRow->aParent[--pRow->nParent];
299 i--;
300 }
301 }
302 }
303 }
304
305
306 /* Find the pChild pointer for each node.
307 **
308 ** The pChild points to the node directly above on the same rail.
309 ** The pChild must be in the same branch. Leaf nodes have a NULL
@@ -360,11 +381,11 @@
381 pRow->iRail = ++p->mxRail;
382 pRow->railInUse = 1<<pRow->iRail;
383 continue;
384 }
385 pRow->iRail = findFreeRail(p, 0, pParent->idx, inUse, pParent->iRail);
386 pParent->aiRiser[pRow->iRail] = pRow->idx;
387 }
388 mask = 1<<pRow->iRail;
389 pRow->railInUse |= mask;
390 if( pRow->pChild==0 ){
391 inUse &= ~mask;
392
+39 -7
--- src/timeline.c
+++ src/timeline.c
@@ -350,27 +350,59 @@
350350
GraphRow *pRow;
351351
int i;
352352
char cSep;
353353
@ <script type="text/JavaScript">
354354
@ /* <![CDATA[ */
355
+
356
+ /* the rowinfo[] array contains all the information needed to generate
357
+ ** the graph. Each entry contains information for a single row:
358
+ **
359
+ ** id: The id of the <div> element for the row. This is an integer.
360
+ ** to get an actual id, prepend "m" to the integer. The top node
361
+ ** is 1 and numbers increase moving down the timeline.
362
+ ** bg: The background color for this row
363
+ ** r: The "rail" that the node for this row sits on. The left-most
364
+ ** rail is 0 and the number increases to the right.
365
+ ** d: True if there is a "descender" - an arrow coming from the bottom
366
+ ** of the page straight up to this node.
367
+ ** mo: "merge-out". If non-negative, this is a rail number on which
368
+ ** a merge arrow travels upward. The merge arrow is drawn upwards
369
+ ** to the row identified by mu:. This value is negative then
370
+ ** node has no merge children and no merge-out line is drawn.
371
+ ** mu: The id of the row which is the top of the merge-out arrow.
372
+ ** md: A bitmask of rails on which merge-arrow descenders should be
373
+ ** drawn from this row to the bottom of the page. The least
374
+ ** significant bit (1) corresponds to rail 0. The 2-bit corresponds
375
+ ** to rail 1. And so forth. This value is 0 if there are no
376
+ ** merge-arrow descenders.
377
+ ** u: Draw a think child-line out of the top of this node and up to
378
+ ** the node with an id equal to this value. 0 if there is no
379
+ ** thick-line riser.
380
+ ** au: An array of integers that define thick-line risers for branches.
381
+ ** The integers are in pairs. For each pair, the first integer is
382
+ ** is the rail on which the riser should run and the second integer
383
+ ** is the id of the node upto which the riser should run.
384
+ ** mi: "merge-in". An array of integer rail numbers from which
385
+ ** merge arrows should be drawn into this node.
386
+ */
355387
cgi_printf("var rowinfo = [\n");
356388
for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
357
- cgi_printf("{id:\"m%d\",bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:",
389
+ cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:",
358390
pRow->idx,
359391
pRow->zBgClr,
360392
pRow->iRail,
361393
pRow->bDescender,
362394
pRow->mergeOut,
363395
pRow->mergeUpto,
364396
pRow->mergeDown,
365
- pRow->aiRaiser[pRow->iRail]
397
+ pRow->aiRiser[pRow->iRail]
366398
);
367399
cSep = '[';
368400
for(i=0; i<GR_MAX_RAIL; i++){
369401
if( i==pRow->iRail ) continue;
370
- if( pRow->aiRaiser[i]>0 ){
371
- cgi_printf("%c%d,%d", cSep, i, pRow->aiRaiser[i]);
402
+ if( pRow->aiRiser[i]>0 ){
403
+ cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
372404
cSep = ',';
373405
}
374406
}
375407
if( cSep=='[' ) cgi_printf("[");
376408
cgi_printf("],mi:");
@@ -497,14 +529,14 @@
497529
@ var canvasDiv = document.getElementById("canvas");
498530
@ while( canvasDiv.hasChildNodes() ){
499531
@ canvasDiv.removeChild(canvasDiv.firstChild);
500532
@ }
501533
@ var canvasY = absoluteY("timelineTable");
502
- @ var left = absoluteX(rowinfo[0].id) - absoluteX("canvas") + 15;
534
+ @ var left = absoluteX("m"+rowinfo[0].id) - absoluteX("canvas") + 15;
503535
@ var width = nrail*20;
504536
@ for(var i in rowinfo){
505
- @ rowinfo[i].y = absoluteY(rowinfo[i].id) + 10 - canvasY;
537
+ @ rowinfo[i].y = absoluteY("m"+rowinfo[i].id) + 10 - canvasY;
506538
@ rowinfo[i].x = left + rowinfo[i].r*20;
507539
@ }
508540
@ var btm = absoluteY("grbtm") + 10 - canvasY;
509541
@ if( btm<32768 ){
510542
@ canvasDiv.innerHTML = '<canvas id="timeline-canvas" '+
@@ -528,11 +560,11 @@
528560
@ }
529561
@ for(var i in rowinfo){
530562
@ drawNode(rowinfo[i], left, btm);
531563
@ }
532564
@ }
533
- @ var lastId = rowinfo[rowinfo.length-1].id;
565
+ @ var lastId = "m"+rowinfo[rowinfo.length-1].id;
534566
@ var lastY = 0;
535567
@ function checkHeight(){
536568
@ var h = absoluteY(lastId);
537569
@ if( h!=lastY ){
538570
@ renderGraph();
539571
540572
ADDED test/graph-test-1.wiki
--- src/timeline.c
+++ src/timeline.c
@@ -350,27 +350,59 @@
350 GraphRow *pRow;
351 int i;
352 char cSep;
353 @ <script type="text/JavaScript">
354 @ /* <![CDATA[ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
355 cgi_printf("var rowinfo = [\n");
356 for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
357 cgi_printf("{id:\"m%d\",bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:",
358 pRow->idx,
359 pRow->zBgClr,
360 pRow->iRail,
361 pRow->bDescender,
362 pRow->mergeOut,
363 pRow->mergeUpto,
364 pRow->mergeDown,
365 pRow->aiRaiser[pRow->iRail]
366 );
367 cSep = '[';
368 for(i=0; i<GR_MAX_RAIL; i++){
369 if( i==pRow->iRail ) continue;
370 if( pRow->aiRaiser[i]>0 ){
371 cgi_printf("%c%d,%d", cSep, i, pRow->aiRaiser[i]);
372 cSep = ',';
373 }
374 }
375 if( cSep=='[' ) cgi_printf("[");
376 cgi_printf("],mi:");
@@ -497,14 +529,14 @@
497 @ var canvasDiv = document.getElementById("canvas");
498 @ while( canvasDiv.hasChildNodes() ){
499 @ canvasDiv.removeChild(canvasDiv.firstChild);
500 @ }
501 @ var canvasY = absoluteY("timelineTable");
502 @ var left = absoluteX(rowinfo[0].id) - absoluteX("canvas") + 15;
503 @ var width = nrail*20;
504 @ for(var i in rowinfo){
505 @ rowinfo[i].y = absoluteY(rowinfo[i].id) + 10 - canvasY;
506 @ rowinfo[i].x = left + rowinfo[i].r*20;
507 @ }
508 @ var btm = absoluteY("grbtm") + 10 - canvasY;
509 @ if( btm<32768 ){
510 @ canvasDiv.innerHTML = '<canvas id="timeline-canvas" '+
@@ -528,11 +560,11 @@
528 @ }
529 @ for(var i in rowinfo){
530 @ drawNode(rowinfo[i], left, btm);
531 @ }
532 @ }
533 @ var lastId = rowinfo[rowinfo.length-1].id;
534 @ var lastY = 0;
535 @ function checkHeight(){
536 @ var h = absoluteY(lastId);
537 @ if( h!=lastY ){
538 @ renderGraph();
539
540 DDED test/graph-test-1.wiki
--- src/timeline.c
+++ src/timeline.c
@@ -350,27 +350,59 @@
350 GraphRow *pRow;
351 int i;
352 char cSep;
353 @ <script type="text/JavaScript">
354 @ /* <![CDATA[ */
355
356 /* the rowinfo[] array contains all the information needed to generate
357 ** the graph. Each entry contains information for a single row:
358 **
359 ** id: The id of the <div> element for the row. This is an integer.
360 ** to get an actual id, prepend "m" to the integer. The top node
361 ** is 1 and numbers increase moving down the timeline.
362 ** bg: The background color for this row
363 ** r: The "rail" that the node for this row sits on. The left-most
364 ** rail is 0 and the number increases to the right.
365 ** d: True if there is a "descender" - an arrow coming from the bottom
366 ** of the page straight up to this node.
367 ** mo: "merge-out". If non-negative, this is a rail number on which
368 ** a merge arrow travels upward. The merge arrow is drawn upwards
369 ** to the row identified by mu:. This value is negative then
370 ** node has no merge children and no merge-out line is drawn.
371 ** mu: The id of the row which is the top of the merge-out arrow.
372 ** md: A bitmask of rails on which merge-arrow descenders should be
373 ** drawn from this row to the bottom of the page. The least
374 ** significant bit (1) corresponds to rail 0. The 2-bit corresponds
375 ** to rail 1. And so forth. This value is 0 if there are no
376 ** merge-arrow descenders.
377 ** u: Draw a think child-line out of the top of this node and up to
378 ** the node with an id equal to this value. 0 if there is no
379 ** thick-line riser.
380 ** au: An array of integers that define thick-line risers for branches.
381 ** The integers are in pairs. For each pair, the first integer is
382 ** is the rail on which the riser should run and the second integer
383 ** is the id of the node upto which the riser should run.
384 ** mi: "merge-in". An array of integer rail numbers from which
385 ** merge arrows should be drawn into this node.
386 */
387 cgi_printf("var rowinfo = [\n");
388 for(pRow=pGraph->pFirst; pRow; pRow=pRow->pNext){
389 cgi_printf("{id:%d,bg:\"%s\",r:%d,d:%d,mo:%d,mu:%d,md:%u,u:%d,au:",
390 pRow->idx,
391 pRow->zBgClr,
392 pRow->iRail,
393 pRow->bDescender,
394 pRow->mergeOut,
395 pRow->mergeUpto,
396 pRow->mergeDown,
397 pRow->aiRiser[pRow->iRail]
398 );
399 cSep = '[';
400 for(i=0; i<GR_MAX_RAIL; i++){
401 if( i==pRow->iRail ) continue;
402 if( pRow->aiRiser[i]>0 ){
403 cgi_printf("%c%d,%d", cSep, i, pRow->aiRiser[i]);
404 cSep = ',';
405 }
406 }
407 if( cSep=='[' ) cgi_printf("[");
408 cgi_printf("],mi:");
@@ -497,14 +529,14 @@
529 @ var canvasDiv = document.getElementById("canvas");
530 @ while( canvasDiv.hasChildNodes() ){
531 @ canvasDiv.removeChild(canvasDiv.firstChild);
532 @ }
533 @ var canvasY = absoluteY("timelineTable");
534 @ var left = absoluteX("m"+rowinfo[0].id) - absoluteX("canvas") + 15;
535 @ var width = nrail*20;
536 @ for(var i in rowinfo){
537 @ rowinfo[i].y = absoluteY("m"+rowinfo[i].id) + 10 - canvasY;
538 @ rowinfo[i].x = left + rowinfo[i].r*20;
539 @ }
540 @ var btm = absoluteY("grbtm") + 10 - canvasY;
541 @ if( btm<32768 ){
542 @ canvasDiv.innerHTML = '<canvas id="timeline-canvas" '+
@@ -528,11 +560,11 @@
560 @ }
561 @ for(var i in rowinfo){
562 @ drawNode(rowinfo[i], left, btm);
563 @ }
564 @ }
565 @ var lastId = "m"+rowinfo[rowinfo.length-1].id;
566 @ var lastY = 0;
567 @ function checkHeight(){
568 @ var h = absoluteY(lastId);
569 @ if( h!=lastY ){
570 @ renderGraph();
571
572 DDED test/graph-test-1.wiki
--- a/test/graph-test-1.wiki
+++ b/test/graph-test-1.wiki
@@ -0,0 +1,10 @@
1
+ </a>experimental&n=100using and - 1000 elementreleasr=release&mionlyOnly c&nomergeaeb1cfe112890e +10:23:00+10:23:00&nd" </a>experimental&n=1000using and - 1000 elementreleasr=release&mionlyOnly c&nome[erimental&n=100using and - 1 ]
2
+ * [and - 1000 elementreleasr=rel ]
3
+ * []
4
+ * [d2e]
5
+ * [/timeline?dl&n=100using and - </a>expea>experimental
6
+
7
+External:
8
+
9
+ * [] - timewarp due to
10
+
--- a/test/graph-test-1.wiki
+++ b/test/graph-test-1.wiki
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
--- a/test/graph-test-1.wiki
+++ b/test/graph-test-1.wiki
@@ -0,0 +1,10 @@
1 </a>experimental&n=100using and - 1000 elementreleasr=release&mionlyOnly c&nomergeaeb1cfe112890e +10:23:00+10:23:00&nd" </a>experimental&n=1000using and - 1000 elementreleasr=release&mionlyOnly c&nome[erimental&n=100using and - 1 ]
2 * [and - 1000 elementreleasr=rel ]
3 * []
4 * [d2e]
5 * [/timeline?dl&n=100using and - </a>expea>experimental
6
7 External:
8
9 * [] - timewarp due to
10

Keyboard Shortcuts

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