@@ -8,19 +8,36 @@ var y_label_width;
88var x_axis ;
99var width ;
1010
11- function offset ( d , i ) {
12- // increase the y offset if the document name changed in this revision
13- if ( i > 0 && data [ i - 1 ] . name !== d . name || d . rev . match ( "^rfc\d+$" ) ) {
14- bar_y += bar_height ;
11+
12+ function expiration_date ( d ) {
13+ return new Date ( d . published . getTime ( ) + 1000 * 60 * 60 * 24 * 185 ) ;
14+ }
15+
16+
17+ function max ( arr ) {
18+ return Math . max . apply ( null , Object . keys ( arr ) . map ( function ( e ) {
19+ return arr [ e ] ;
20+ } ) ) ;
21+ }
22+
23+
24+ function offset ( d ) {
25+ if ( bar_y [ d . name ] === undefined ) {
26+ var m = Object . keys ( bar_y ) . length === 0 ? - bar_height : max ( bar_y ) ;
27+ bar_y [ d . name ] = m + bar_height ;
1528 }
16- return "translate(" + x_scale ( d . published ) + ", " + bar_y + ")" ;
29+ return "translate(" + x_scale ( d . published ) + ", " + bar_y [ d . name ] + ")" ;
1730}
1831
1932
2033function bar_width ( d , i ) {
21- if ( i < data . length - 1 ) {
22- return x_scale ( data [ i + 1 ] . published ) - x_scale ( d . published ) ;
34+ // check for next rev of this name
35+ for ( i ++ ; i < data . length ; i ++ ) {
36+ if ( data [ i ] . name === d . name ) { break ; }
2337 }
38+
39+ var w = i === data . length ? expiration_date ( d ) : data [ i ] . published ;
40+ return x_scale ( w ) - x_scale ( d . published ) ;
2441}
2542
2643
@@ -33,10 +50,21 @@ function scale_x() {
3350 d3 . max ( data , function ( d ) { return d . published ; } )
3451 ] ) . range ( [ y_label_width , width ] ) ;
3552
53+ // resort data by publication time to suppress some ticks if they are closer
54+ // than 12px, and don't add a tick for the final pseudo entry
55+ var tv = data
56+ . slice ( 0 , - 1 )
57+ . sort ( function ( a , b ) { return a . published - b . published ; } )
58+ . map ( function ( d , i , arr ) {
59+ if ( i === 0 ||
60+ x_scale ( d . published ) > x_scale ( arr [ i - 1 ] . published ) + 12 ) {
61+ return d . published ;
62+ }
63+ } ) . filter ( function ( d ) { return d !== undefined ; } ) ;
64+
3665 x_axis = d3 . svg . axis ( )
3766 . scale ( x_scale )
38- // don't add a tick for the pseudo entry
39- . tickValues ( data . slice ( 0 , - 1 ) . map ( function ( d ) { return d . published ; } ) )
67+ . tickValues ( tv )
4068 . tickFormat ( d3 . time . format ( "%b %Y" ) )
4169 . orient ( "bottom" ) ;
4270}
@@ -51,10 +79,11 @@ function update_x_axis() {
5179
5280
5381function update_timeline ( ) {
54- bar_y = 0 ;
82+ bar_y = { } ;
5583 scale_x ( ) ;
5684 var chart = d3 . select ( "#timeline svg" ) . attr ( "width" , width ) ;
57- var bar = chart . selectAll ( "g" ) . data ( data ) ;
85+ // enter data (skip the last pseudo entry)
86+ var bar = chart . selectAll ( "g" ) . data ( data . slice ( 0 , - 1 ) ) ;
5887 bar . attr ( "transform" , offset ) . select ( "rect" ) . attr ( "width" , bar_width ) ;
5988 update_x_axis ( ) ;
6089}
@@ -84,7 +113,7 @@ function draw_timeline() {
84113 } ) ;
85114
86115 var y_labels = data
87- . map ( function ( elem ) { return elem . name ; } )
116+ . map ( function ( d ) { return d . name ; } )
88117 . filter ( function ( val , i , self ) { return self . indexOf ( val ) === i ; } ) ;
89118
90119 // calculate the width of the widest y axis label by drawing them off-screen
@@ -107,19 +136,28 @@ function draw_timeline() {
107136 // update
108137 update_timeline ( ) ;
109138
110- // enter
111- var bar = chart . selectAll ( "g" ) . data ( data ) ;
139+ // re-order data by document name, for CSS background color alternation
140+ var ndata = [ ] ;
141+ y_labels . forEach ( function ( l ) {
142+ ndata = ndata . concat ( data . filter ( function ( d ) { return d . name === l ; } ) ) ;
143+ } ) ;
144+ data = ndata ;
145+
146+ // enter data (skip the last pseudo entry)
147+ var bar = chart . selectAll ( "g" ) . data ( data . slice ( 0 , - 1 ) ) ;
112148 var g = bar . enter ( )
113149 . append ( "g" )
114150 . attr ( {
115151 class : "bar" ,
116152 transform : offset
117153 } ) ;
118- g . append ( "rect" )
119- . attr ( {
120- height : bar_height ,
121- width : bar_width
122- } ) ;
154+ g . append ( "a" )
155+ . attr ( "xlink:href" , function ( d ) { return d . url ; } )
156+ . append ( "rect" )
157+ . attr ( {
158+ height : bar_height ,
159+ width : bar_width
160+ } ) ;
123161 g . append ( "text" )
124162 . attr ( {
125163 x : 3 ,
@@ -129,11 +167,11 @@ function draw_timeline() {
129167
130168 // since the gradient is defined inside the SVG, we need to set the CSS
131169 // style here, so the relative URL works
132- $ ( "#timeline .bar:nth- last-child(2) rect" ) . css ( "fill" , "url(#gradient)" ) ;
170+ $ ( "#timeline .bar:last-child rect" ) . css ( "fill" , "url(#gradient)" ) ;
133171
134172 var y_scale = d3 . scale . ordinal ( )
135173 . domain ( y_labels )
136- . rangePoints ( [ 0 , bar_y ] ) ;
174+ . rangePoints ( [ 0 , max ( bar_y ) + bar_height ] ) ;
137175
138176 var y_axis = d3 . svg . axis ( )
139177 . scale ( y_scale )
@@ -142,7 +180,7 @@ function draw_timeline() {
142180
143181 chart . append ( "g" ) . attr ( {
144182 class : "x axis" ,
145- transform : "translate(0, " + bar_y + ")"
183+ transform : "translate(0, " + ( max ( bar_y ) + bar_height ) + ")"
146184 } ) ;
147185 update_x_axis ( ) ;
148186
@@ -160,7 +198,7 @@ function draw_timeline() {
160198 d3 . select ( ".x.axis" ) . each ( function ( ) {
161199 x_label_height = this . getBBox ( ) . height ;
162200 } ) ;
163- chart . attr ( "height" , bar_y + x_label_height ) ;
201+ chart . attr ( "height" , max ( bar_y ) + bar_height + x_label_height ) ;
164202}
165203
166204
@@ -172,10 +210,12 @@ d3.json("doc.json", function(error, json) {
172210 // make js dates out of publication dates
173211 data . forEach ( function ( d ) { d . published = new Date ( d . published ) ; } ) ;
174212
175- // add pseudo entry 185 days after last rev (when the ID will expire)
176- var pseudo = new Date ( data [ data . length - 1 ] . published . getTime ( ) +
177- 1000 * 60 * 60 * 24 * 185 ) ;
178- data . push ( { name : "" , rev : "" , published : pseudo } ) ;
213+ // add pseudo entry when the ID will expire
214+ data . push ( {
215+ name : "" ,
216+ rev : "" ,
217+ published : expiration_date ( data [ data . length - 1 ] )
218+ } ) ;
179219 draw_timeline ( ) ;
180220 }
181221} ) ;
0 commit comments