@ -722,7 +722,10 @@ nv.models.line = function() {
points . enter ( ) . append ( 'circle' )
points . enter ( ) . append ( 'circle' )
. attr ( 'cx' , function ( d ) { return x0 ( getX ( d ) ) } )
. attr ( 'cx' , function ( d ) { return x0 ( getX ( d ) ) } )
. attr ( 'cy' , function ( d ) { return y0 ( getY ( d ) ) } ) ;
. attr ( 'cy' , function ( d ) { return y0 ( getY ( d ) ) } ) ;
//d3.transition(points.exit())
d3 . transition ( points . exit ( ) )
. attr ( 'cx' , function ( d ) { return x ( getX ( d ) ) } )
. attr ( 'cy' , function ( d ) { return y ( getY ( d ) ) } )
. remove ( ) ;
d3 . transition ( lines . exit ( ) . selectAll ( 'circle.point' ) )
d3 . transition ( lines . exit ( ) . selectAll ( 'circle.point' ) )
. attr ( 'cx' , function ( d ) { return x ( getX ( d ) ) } )
. attr ( 'cx' , function ( d ) { return x ( getX ( d ) ) } )
. attr ( 'cy' , function ( d ) { return y ( getY ( d ) ) } )
. attr ( 'cy' , function ( d ) { return y ( getY ( d ) ) } )
@ -839,16 +842,14 @@ nv.models.lineWithFocus = function() {
legend = nv . models . legend ( ) . height ( 30 ) ,
legend = nv . models . legend ( ) . height ( 30 ) ,
focus = nv . models . line ( ) ,
focus = nv . models . line ( ) ,
context = nv . models . line ( ) . dotRadius ( . 1 ) . interactive ( false ) ,
context = nv . models . line ( ) . dotRadius ( . 1 ) . interactive ( false ) ,
dispatch = d3 . dispatch ( 'tooltipShow' , 'tooltipHide' ) ;
dispatch = d3 . dispatch ( 'tooltipShow' , 'tooltipHide' ) ,
brush = d3 . svg . brush ( )
. x ( x2 ) ;
var brush = d3 . svg . brush ( )
. x ( x2 )
. on ( 'brush' , onBrush ) ;
//var wrap, gEnter, g, focus, focusLines, contextWrap, focusWrap, contextLines; //brought all variables to this scope for use within brush function... is this a bad idea?
var wrap , gEnter , g , focus , focusLines , contextWrap , focusWrap , contextLines ; //brought all variables to this scope for use within brush function... is this a bad idea?
//var seriesData; //Temporarily bringing this data to this scope.... may be bad idea (same with above).. may need to rethink brushing
var seriesData ; //Temporarily bringing this data to this scope.... may be bad idea (same with above).. may need to rethink brushing
function chart ( selection ) {
function chart ( selection ) {
selection . each ( function ( data ) {
selection . each ( function ( data ) {
@ -865,6 +866,7 @@ nv.models.lineWithFocus = function() {
y . domain ( y2 . domain ( ) )
y . domain ( y2 . domain ( ) )
. range ( [ height1 - margin . top - margin . bottom , 0 ] ) ;
. range ( [ height1 - margin . top - margin . bottom , 0 ] ) ;
brush . on ( 'brush' , onBrush ) ;
focus
focus
. width ( width - margin . left - margin . right )
. width ( width - margin . left - margin . right )
@ -881,10 +883,11 @@ nv.models.lineWithFocus = function() {
} ) . filter ( function ( d , i ) { return ! data [ i ] . disabled } ) )
} ) . filter ( function ( d , i ) { return ! data [ i ] . disabled } ) )
updateFocus ( ) ;
wrap = d3 . select ( this ) . selectAll ( 'g.wrap' ) . data ( [ data ] ) ;
var wrap = d3 . select ( this ) . selectAll ( 'g.wrap' ) . data ( [ data ] ) ;
gEnter = wrap . enter ( ) . append ( 'g' ) . attr ( 'class' , 'wrap d3lineWithFocus' ) . append ( 'g' ) ;
var gEnter = wrap . enter ( ) . append ( 'g' ) . attr ( 'class' , 'wrap d3lineWithFocus' ) . append ( 'g' ) ;
gEnter . append ( 'g' ) . attr ( 'class' , 'focus' ) ;
gEnter . append ( 'g' ) . attr ( 'class' , 'focus' ) ;
gEnter . append ( 'g' ) . attr ( 'class' , 'context' ) ;
gEnter . append ( 'g' ) . attr ( 'class' , 'context' ) ;
@ -892,7 +895,7 @@ nv.models.lineWithFocus = function() {
g = wrap . select ( 'g' )
var g = wrap . select ( 'g' )
//.attr('transform', 'translate(0,0)');
//.attr('transform', 'translate(0,0)');
@ -916,7 +919,7 @@ nv.models.lineWithFocus = function() {
// ********** FOCUS **********
// ********** FOCUS **********
focusWrap = g . select ( '.focus' )
var focusWrap = g . select ( '.focus' )
. attr ( 'transform' , 'translate(' + margin . left + ',' + margin . top + ')' ) ;
. attr ( 'transform' , 'translate(' + margin . left + ',' + margin . top + ')' ) ;
gEnter . select ( '.focus' ) . append ( 'g' ) . attr ( 'class' , 'x axis' ) ;
gEnter . select ( '.focus' ) . append ( 'g' ) . attr ( 'class' , 'x axis' ) ;
@ -924,7 +927,7 @@ nv.models.lineWithFocus = function() {
gEnter . select ( '.focus' ) . append ( 'g' ) . attr ( 'class' , 'focusLines' ) ;
gEnter . select ( '.focus' ) . append ( 'g' ) . attr ( 'class' , 'focusLines' ) ;
focusLines = g . select ( '.focusLines' )
var focusLines = focusWrap . select ( '.focusLines' )
. datum ( data . filter ( function ( d ) { return ! d . disabled } ) )
. datum ( data . filter ( function ( d ) { return ! d . disabled } ) )
d3 . transition ( focusLines ) . call ( focus ) ;
d3 . transition ( focusLines ) . call ( focus ) ;
@ -936,7 +939,7 @@ nv.models.lineWithFocus = function() {
. ticks ( width / 100 )
. ticks ( width / 100 )
. tickSize ( - ( height1 - margin . top - margin . bottom ) , 0 ) ;
. tickSize ( - ( height1 - margin . top - margin . bottom ) , 0 ) ;
g . select ( '.x.axis' )
focusWrap . select ( '.x.axis' )
. attr ( 'transform' , 'translate(0,' + y . range ( ) [ 0 ] + ')' ) ;
. attr ( 'transform' , 'translate(0,' + y . range ( ) [ 0 ] + ')' ) ;
d3 . transition ( g . select ( '.x.axis' ) )
d3 . transition ( g . select ( '.x.axis' ) )
. call ( xAxis ) ;
. call ( xAxis ) ;
@ -955,7 +958,7 @@ nv.models.lineWithFocus = function() {
// ********** CONTEXT **********
// ********** CONTEXT **********
contextWrap = g . select ( '.context' )
var contextWrap = g . select ( '.context' )
. attr ( 'transform' , 'translate(' + margin2 . left + ',' + height1 + ')' ) ;
. attr ( 'transform' , 'translate(' + margin2 . left + ',' + height1 + ')' ) ;
gEnter . select ( '.context' ) . append ( 'g' ) . attr ( 'class' , 'x2 axis' ) ;
gEnter . select ( '.context' ) . append ( 'g' ) . attr ( 'class' , 'x2 axis' ) ;
@ -968,7 +971,7 @@ nv.models.lineWithFocus = function() {
. attr ( 'y' , - 5 )
. attr ( 'y' , - 5 )
. attr ( 'height' , height2 + 4 ) ;
. attr ( 'height' , height2 + 4 ) ;
contextLines = contextWrap . select ( '.contextLines' )
var contextLines = contextWrap . select ( '.contextLines' )
. datum ( data . filter ( function ( d ) { return ! d . disabled } ) )
. datum ( data . filter ( function ( d ) { return ! d . disabled } ) )
d3 . transition ( contextLines ) . call ( context ) ;
d3 . transition ( contextLines ) . call ( context ) ;
@ -1041,40 +1044,53 @@ nv.models.lineWithFocus = function() {
dispatch . tooltipHide ( e ) ;
dispatch . tooltipHide ( e ) ;
} ) ;
} ) ;
} ) ;
return chart ;
}
// ********** FUNCTIONS **********
function onBrush ( ) {
function onBrush ( ) {
updateFocus ( ) ;
focusLines . call ( focus )
wrap . select ( '.x.axis' ) . call ( xAxis ) ;
wrap . select ( '.y.axis' ) . call ( yAxis ) ;
}
function updateFocus ( ) {
var yDomain = brush . empty ( ) ? y2 . domain ( ) : d3 . extent ( d3 . merge ( seriesData ) . filter ( function ( d ) {
var yDomain = brush . empty ( ) ? y2 . domain ( ) : d3 . extent ( d3 . merge ( seriesData ) . filter ( function ( d ) {
return getX ( d ) >= brush . extent ( ) [ 0 ] && getX ( d ) <= brush . extent ( ) [ 1 ] ;
return getX ( d ) >= brush . extent ( ) [ 0 ] && getX ( d ) <= brush . extent ( ) [ 1 ] ;
} ) , getY ) ;
} ) , getY ) ; //This doesn't account for the 1 point before and the 1 point after the domain. Would fix, but likely need to change entire methodology here
if ( typeof yDomain [ 0 ] == 'undefined' ) yDomain = y2 . domain ( ) ;
if ( typeof yDomain [ 0 ] == 'undefined' ) yDomain = y2 . domain ( ) ; //incase the brush doesn't cover a single point
x . domain ( brush . empty ( ) ? x2 . domain ( ) : brush . extent ( ) ) ;
x . domain ( brush . empty ( ) ? x2 . domain ( ) : brush . extent ( ) ) ;
y . domain ( yDomain ) ;
y . domain ( yDomain ) ;
//y.domain(brush.empty() ? y2.domain() : d3.extent(d3.merge(seriesData).filter(function(d) {
//return getX(d) >= brush.extent()[0] && getX(d) <= brush.extent()[1];
//TODO: Rethink this... performance is horrible, likely need to cut off focus data to within the range
//}), getY) || y2.domain() );
// If I limit the data for focusLines would want to include 1 point before and after the extent,
// Need to figure out an optimized way to accomplish this.
// ***One concern is to try not to make the assumption that all lines are of the same length, and
// points with the same index have the same x value (while this is true in our test cases, may
// no always be)
focus . xDomain ( x . domain ( ) ) ;
focus . xDomain ( x . domain ( ) ) ;
focus . yDomain ( y . domain ( ) ) ;
focus . yDomain ( y . domain ( ) ) ;
}
focusLines . call ( focus )
wrap . select ( '.x.axis' ) . call ( xAxis ) ;
} ) ;
wrap . select ( '.y.axis' ) . call ( yAxis ) ;
return chart ;
}
}
// ********** FUNCTIONS **********
// ********** PUBLIC ACCESSORS **********
// ********** PUBLIC ACCESSORS **********