@@ -7,7 +7,7 @@ var bar_height;
77var y_label_width ;
88var x_axis ;
99var width ;
10-
10+ var now ;
1111
1212function expiration_date ( d ) {
1313 return new Date ( d . published . getTime ( ) + 1000 * 60 * 60 * 24 * 185 ) ;
@@ -31,12 +31,14 @@ function offset(d) {
3131
3232
3333function bar_width ( d , i ) {
34- // check for next rev of this name
34+ // check for next rev of this name, or published RFC
3535 for ( i ++ ; i < data . length ; i ++ ) {
36- if ( data [ i ] . name === d . name ) { break ; }
36+ if ( data [ i ] . name === d . name || data [ i ] . name . match ( / ^ r f c / ) ) { break ; }
3737 }
3838
3939 var w = i === data . length ? expiration_date ( d ) : data [ i ] . published ;
40+ // don't extend the bar past the expiration date of the document
41+ w = w > expiration_date ( d ) ? expiration_date ( d ) : w ;
4042 return x_scale ( w ) - x_scale ( d . published ) ;
4143}
4244
@@ -50,11 +52,15 @@ function scale_x() {
5052 d3 . max ( data , function ( d ) { return d . published ; } )
5153 ] ) . range ( [ y_label_width , width ] ) ;
5254
55+
56+ // if the end of the timeline is past the current date, show it
57+ var tv = data . slice ( 0 , - 1 ) ;
58+ now = Date . now ( ) ;
59+ if ( tv [ tv . length - 1 ] . published > now ) { tv . push ( new Date ( now ) ) ; }
60+
5361 // resort data by publication time to suppress some ticks if they are closer
5462 // 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 ; } )
63+ tv = tv . sort ( function ( a , b ) { return a . published - b . published ; } )
5864 . map ( function ( d , i , arr ) {
5965 if ( i === 0 ||
6066 x_scale ( d . published ) > x_scale ( arr [ i - 1 ] . published ) + 12 ) {
@@ -65,7 +71,10 @@ function scale_x() {
6571 x_axis = d3 . svg . axis ( )
6672 . scale ( x_scale )
6773 . tickValues ( tv )
68- . tickFormat ( d3 . time . format ( "%b %Y" ) )
74+ . tickFormat ( function ( d ) {
75+ if ( d . getTime ( ) < now ) { return d3 . time . format ( "%b %Y" ) ( d ) ; }
76+ return "Now" ;
77+ } )
6978 . orient ( "bottom" ) ;
7079}
7180
@@ -94,24 +103,38 @@ function draw_timeline() {
94103
95104 var div = $ ( "#timeline" ) ;
96105 if ( div . is ( ":empty" ) ) {
97- div . append ( "<svg></svg>" ) ;
106+ div . append ( "<svg xmlns:xlink='http://www.w3.org/1999/xlink' ></svg>" ) ;
98107 }
99108 var chart = d3 . select ( "#timeline svg" ) . attr ( "width" , width ) ;
100109
101- var gradient = chart . append ( "defs" )
102- . append ( "linearGradient" )
103- . attr ( "id" , "gradient " ) ;
104- gradient . append ( "stop" )
110+ var defs = chart . append ( "defs" ) ;
111+ var fade = defs . append ( "linearGradient" )
112+ . attr ( "id" , "maskGradient " ) ;
113+ fade . append ( "stop" )
105114 . attr ( {
106- class : "gradient left" ,
107- offset : 0
115+ offset : 0.9 ,
116+ "stop-color" : "white" ,
117+ "stop-opacity" : 1
108118 } ) ;
109- gradient . append ( "stop" )
119+ fade . append ( "stop" )
110120 . attr ( {
111- class : "gradient right" ,
112- offset : 1
121+ offset : 1 ,
122+ "stop-color" : "white" ,
123+ "stop-opacity" : 0
113124 } ) ;
114125
126+ defs . append ( "mask" )
127+ . attr ( {
128+ id : "fade" ,
129+ maskContentUnits : "objectBoundingBox"
130+ } )
131+ . append ( "rect" )
132+ . attr ( {
133+ height : 1 ,
134+ width : 1 ,
135+ fill : "url(#maskGradient)"
136+ } ) ;
137+
115138 var y_labels = data
116139 . map ( function ( d ) { return d . name ; } )
117140 . filter ( function ( val , i , self ) { return self . indexOf ( val ) === i ; } ) ;
@@ -156,19 +179,23 @@ function draw_timeline() {
156179 . append ( "rect" )
157180 . attr ( {
158181 height : bar_height ,
159- width : bar_width
182+ width : bar_width ,
183+ mask : function ( d , i ) {
184+ // apply gradient it the document expired
185+ if ( bar_width ( d , i ) >= x_scale ( expiration_date ( d ) ) -
186+ x_scale ( d . published ) ) {
187+ return "url(#fade)" ;
188+ }
189+ }
160190 } ) ;
191+
161192 g . append ( "text" )
162193 . attr ( {
163194 x : 3 ,
164195 y : bar_height / 2
165196 } )
166197 . text ( function ( d ) { return d . rev ; } ) ;
167198
168- // since the gradient is defined inside the SVG, we need to set the CSS
169- // style here, so the relative URL works
170- $ ( "#timeline .bar:last-child rect" ) . css ( "fill" , "url(#gradient)" ) ;
171-
172199 var y_scale = d3 . scale . ordinal ( )
173200 . domain ( y_labels )
174201 . rangePoints ( [ 0 , max ( bar_y ) + bar_height ] ) ;
0 commit comments