@@ -57,26 +57,6 @@ export class Legend extends Element {
5757 */
5858 this . _hoveredItem = null ;
5959
60- this . navigation = {
61- active : false ,
62- page : 0 ,
63- totalPages : 0 ,
64- itemWidth : 0 ,
65- itemHeight : 0 ,
66- navWidth : 0 ,
67- navHeight : 0 ,
68- maxBlocks : 0 ,
69- blocks : undefined ,
70- text : undefined ,
71- prev : undefined ,
72- next : undefined ,
73- legendItems : undefined ,
74- _width : 0 ,
75- _height : 0 ,
76- _maxWidth : 0 ,
77- _maxHeight : 0 ,
78- } ;
79-
8060 // Are we in doughnut mode which has a different data type
8161 this . doughnutMode = false ;
8262
@@ -98,6 +78,7 @@ export class Legend extends Element {
9878 this . position = undefined ;
9979 this . weight = undefined ;
10080 this . fullSize = undefined ;
81+ this . navigation = undefined ;
10182 }
10283
10384 update ( maxWidth , maxHeight , margins ) {
@@ -139,17 +120,16 @@ export class Legend extends Element {
139120 legendItems . reverse ( ) ;
140121 }
141122
142- this . navigation . legendItems = this . legendItems = legendItems ;
123+ this . legendItems = legendItems ;
143124 this . _computeNavigation ( ) ;
144125 }
145126
146127 /**
147128 * @private
148129 */
149- _resetNavigation ( ) {
150- if ( this . navigation . active ) {
151- Object . assign ( this . navigation , {
152- active : false ,
130+ _initNavigation ( override ) {
131+ if ( ! this . navigation ) {
132+ this . navigation = {
153133 page : 0 ,
154134 totalPages : 0 ,
155135 itemWidth : 0 ,
@@ -166,7 +146,11 @@ export class Legend extends Element {
166146 _height : 0 ,
167147 _maxWidth : 0 ,
168148 _maxHeight : 0 ,
169- } ) ;
149+ } ;
150+ }
151+
152+ if ( override ) {
153+ Object . assign ( this . navigation , override ) ;
170154 }
171155 }
172156
@@ -178,25 +162,28 @@ export class Legend extends Element {
178162 const { navigation : navOpts , labels : labelOpts } = options ;
179163
180164 if ( ! ( navOpts && navOpts . display ) ) {
181- this . _resetNavigation ( ) ;
165+ this . navigation = undefined ;
182166 return ;
183167 }
184168 const isHorizontal = this . isHorizontal ( ) ;
185169
186- this . navigation . active = true ;
187- this . navigation . totalPages = 0 ;
188- this . navigation . _width = this . navigation . _height = 0 ;
189- this . navigation . _maxWidth = this . navigation . _maxHeight = 0 ;
190- this . navigation . itemWidth = this . navigation . itemHeight = 0 ;
191- this . navigation . maxBlocks = 0 ;
170+ this . _initNavigation ( {
171+ totalPages : 0 ,
172+ _width : 0 ,
173+ _height : 0 ,
174+ _maxWidth : 0 ,
175+ _maxHeight : 0 ,
176+ itemWidth : 0 ,
177+ itemHeight : 0 ,
178+ maxBlocks : 0 ,
179+ } ) ;
192180
193- const { arrowSize} = navOpts ;
194181 const labelFont = toFont ( labelOpts . font ) ;
195182 const { boxWidth, itemHeight : _itemHeight } = getBoxSize ( labelOpts , labelFont . size ) ;
196183 const font = toFont ( navOpts . font ) ;
197184
198185 const padding = toPadding ( navOpts . padding ) ;
199- this . navigation . navHeight = Math . max ( font . size , arrowSize ) + padding . height ;
186+ this . navigation . navHeight = Math . max ( font . size , navOpts . arrowSize ) + padding . height ;
200187
201188 const grid = getGridAxis ( navOpts . grid ) ;
202189
@@ -325,17 +312,16 @@ export class Legend extends Element {
325312 }
326313
327314 buildNavigation ( ) {
328- const { ctx, options : { align, navigation : navOpts , labels : labelOpts } } = this ;
329- const { active, totalPages, navHeight} = this . navigation ;
330-
331- if ( ! active ) {
315+ if ( ! this . navigation ) {
332316 return ;
333317 }
318+ const { ctx, options : { align, navigation : navOpts , labels : labelOpts } } = this ;
319+ const { totalPages, navHeight} = this . navigation ;
334320
335321 const font = toFont ( navOpts . font ) ;
336322
337323 if ( totalPages < 1 || ( totalPages === 1 && navOpts . display === 'auto' ) ) {
338- this . _resetNavigation ( ) ;
324+ this . navigation = undefined ;
339325 return ;
340326 }
341327
@@ -394,7 +380,12 @@ export class Legend extends Element {
394380 */
395381 _getLegendItemWidth ( legendItem , boxWidth , labelFont ) {
396382 const hitboxWidth = calculateItemWidth ( legendItem , boxWidth , labelFont , this . ctx ) ;
397- const itemWidth = this . navigation . itemWidth || hitboxWidth ;
383+ let itemWidth = hitboxWidth ;
384+
385+ if ( this . navigation && this . navigation . itemWidth ) {
386+ itemWidth = this . navigation . itemWidth ;
387+ }
388+
398389 return { itemWidth, hitboxWidth} ;
399390 }
400391
@@ -403,10 +394,25 @@ export class Legend extends Element {
403394 */
404395 _getLegendItemHeight ( legendItem , _itemHeight , labelFont ) {
405396 const hitboxHeight = calculateItemHeight ( _itemHeight , legendItem , labelFont . lineHeight ) ;
406- const itemHeight = this . navigation . itemHeight || hitboxHeight ;
397+ let itemHeight = hitboxHeight ;
398+
399+ if ( this . navigation && this . navigation . itemHeight ) {
400+ itemHeight = this . navigation . itemHeight ;
401+ }
402+
407403 return { itemHeight, hitboxHeight} ;
408404 }
409405
406+ /**
407+ * @private
408+ */
409+ _getVisibleLegendItems ( ) {
410+ if ( this . navigation ) {
411+ return this . navigation . legendItems ;
412+ }
413+ return this . legendItems ;
414+ }
415+
410416 fit ( ) {
411417 const { options, ctx} = this ;
412418
@@ -433,15 +439,23 @@ export class Legend extends Element {
433439 if ( isHorizontal ) {
434440 width = this . maxWidth ; // fill all the width
435441 height = this . _fitRows ( titleHeight , labelFont , boxWidth , itemHeight ) + 10 ;
442+
443+ if ( this . navigation ) {
444+ height = this . navigation . _height ;
445+ }
436446 } else {
437447 height = this . maxHeight ; // fill all the height
438448 width = this . _fitCols ( titleHeight , labelFont , boxWidth , itemHeight ) + 10 ;
449+
450+ if ( this . navigation ) {
451+ width = this . navigation . _width ;
452+ }
439453 }
440454
441455 const maxWidth = isHorizontal ? this . maxWidth : ( options . maxWidth || this . maxWidth ) ;
442456 const maxHeight = isHorizontal ? ( options . maxHeight || this . maxHeight ) : this . maxHeight ;
443- this . width = Math . min ( this . navigation . _width || width , maxWidth ) ;
444- this . height = Math . min ( this . navigation . _height || height , maxHeight ) ;
457+ this . width = Math . min ( width , maxWidth ) ;
458+ this . height = Math . min ( height , maxHeight ) ;
445459 }
446460
447461 /**
@@ -460,7 +474,8 @@ export class Legend extends Element {
460474 let row = 0 ;
461475 let top = 0 ;
462476 let currentLineHeight = 0 ;
463- this . navigation . legendItems . forEach ( ( legendItem , i ) => {
477+
478+ this . _getVisibleLegendItems ( ) . forEach ( ( legendItem , i ) => {
464479 const { itemWidth, itemHeight, hitboxWidth, hitboxHeight} = this . _getLegendItemSize ( legendItem , boxWidth , _itemHeight , labelFont ) ;
465480
466481 if ( i > 0 && lineWidths [ lineWidths . length - 1 ] + itemWidth + 2 * padding > maxWidth ) {
@@ -487,7 +502,11 @@ export class Legend extends Element {
487502 const { maxHeight, options : { labels : { padding} } } = this ;
488503 const hitboxes = this . legendHitBoxes = [ ] ;
489504 const columnSizes = this . columnSizes = [ ] ;
490- const heightLimit = maxHeight - titleHeight - this . navigation . navHeight ;
505+ let heightLimit = maxHeight - titleHeight ;
506+
507+ if ( this . navigation ) {
508+ heightLimit -= this . navigation . navHeight ;
509+ }
491510
492511 let totalWidth = padding ;
493512 let currentColWidth = 0 ;
@@ -496,7 +515,7 @@ export class Legend extends Element {
496515 let left = 0 ;
497516 let col = 0 ;
498517
499- this . navigation . legendItems . forEach ( ( legendItem , i ) => {
518+ this . _getVisibleLegendItems ( ) . forEach ( ( legendItem , i ) => {
500519 const { itemWidth, itemHeight, hitboxWidth, hitboxHeight} = this . _getLegendItemSize ( legendItem , boxWidth , _itemHeight , labelFont ) ;
501520
502521 // If too tall, go to new column
@@ -545,7 +564,11 @@ export class Legend extends Element {
545564 left += hitbox . offsetWidth + padding ;
546565 }
547566 } else {
548- const bottom = this . bottom - this . navigation . navHeight ;
567+ let bottom = this . bottom ;
568+
569+ if ( this . navigation ) {
570+ bottom -= this . navigation . navHeight ;
571+ }
549572
550573 let col = 0 ;
551574 let top = _alignStartEnd ( align , this . top + titleHeight + padding , bottom - this . columnSizes [ col ] . height ) ;
@@ -674,7 +697,11 @@ export class Legend extends Element {
674697 // Horizontal
675698 const isHorizontal = this . isHorizontal ( ) ;
676699 const titleHeight = this . _computeTitleHeight ( ) ;
677- const bottom = this . bottom - this . navigation . navHeight ;
700+ let bottom = this . bottom ;
701+
702+ if ( this . navigation ) {
703+ bottom -= this . navigation . navHeight ;
704+ }
678705
679706 if ( isHorizontal ) {
680707 cursor = {
@@ -693,7 +720,7 @@ export class Legend extends Element {
693720 overrideTextDirection ( this . ctx , opts . textDirection ) ;
694721
695722 let currentLineHeight = 0 ;
696- this . navigation . legendItems . forEach ( ( legendItem , i ) => {
723+ this . _getVisibleLegendItems ( ) . forEach ( ( legendItem , i ) => {
697724 ctx . strokeStyle = legendItem . fontColor ; // for strikethrough effect
698725 ctx . fillStyle = legendItem . fontColor ; // render in correct colour
699726
@@ -745,10 +772,13 @@ export class Legend extends Element {
745772 * @private
746773 */
747774 _drawNavigation ( ) {
775+ if ( ! this . navigation ) {
776+ return ;
777+ }
748778 const { ctx, options : { navigation : navOpts } } = this ;
749- const { active , page, totalPages, maxBlocks, prev, next, text} = this . navigation ;
779+ const { page, totalPages, maxBlocks, prev, next, text} = this . navigation ;
750780
751- if ( ! active || ( totalPages <= 1 && navOpts . display === 'auto' ) ) {
781+ if ( totalPages <= 1 && navOpts . display === 'auto' ) {
752782 return ;
753783 }
754784
@@ -813,13 +843,20 @@ export class Legend extends Element {
813843
814844 if ( this . isHorizontal ( ) ) {
815845 // Move left / right so that the title is above the legend lines
816- maxWidth = ( this . navigation . _maxWidth || Math . max ( ...this . lineWidths ) ) + labelOpts . padding ;
846+ maxWidth = ( this . navigation ? this . navigation . _maxWidth : Math . max ( ...this . lineWidths ) ) + labelOpts . padding ;
817847 y = this . top + topPaddingPlusHalfFontSize ;
818848 left = _alignStartEnd ( options . align , left , this . right - maxWidth ) ;
819849 } else {
820850 // Move down so that the title is above the legend stack in every alignment
821- const maxHeight = ( this . navigation . _maxHeight || this . columnSizes . reduce ( ( acc , size ) => Math . max ( acc , size . height ) , 0 ) )
822- + labelOpts . padding + this . _computeTitleHeight ( ) + this . navigation . navHeight ;
851+ let maxHeight ;
852+
853+ if ( this . navigation ) {
854+ maxHeight = this . navigation . _maxHeight + this . navigation . navHeight ;
855+ } else {
856+ maxHeight = this . columnSizes . reduce ( ( acc , size ) => Math . max ( acc , size . height ) , 0 ) ;
857+ }
858+
859+ maxHeight += labelOpts . padding + this . _computeTitleHeight ( ) ;
823860 y = topPaddingPlusHalfFontSize + _alignStartEnd ( options . align , this . top , this . bottom - maxHeight ) ;
824861 }
825862
@@ -889,11 +926,10 @@ export class Legend extends Element {
889926 * @private
890927 */
891928 _getNavigationDirAt ( x , y ) {
892- const { prev, next} = this . navigation ;
893-
894- if ( ! ( prev && next ) ) {
929+ if ( ! ( this . navigation && this . navigation . prev && this . navigation . next ) ) {
895930 return 0 ;
896931 }
932+ const { prev, next} = this . navigation ;
897933
898934 const { arrowSize} = this . options . navigation ;
899935 // Add a padding to the clickable area (30% of the arrow size)
@@ -915,19 +951,20 @@ export class Legend extends Element {
915951 * @private
916952 */
917953 _getLegendItemAt ( x , y ) {
918- let i , hitBox , lh ;
919-
920954 if ( _isBetween ( x , this . left , this . right )
921955 && _isBetween ( y , this . top , this . bottom ) ) {
922956 // See if we are touching one of the dataset boxes
923- lh = this . legendHitBoxes ;
924- for ( i = 0 ; i < lh . length ; ++ i ) {
957+ const lh = this . legendHitBoxes ;
958+ const legendItems = this . _getVisibleLegendItems ( ) ;
959+ let hitBox ;
960+
961+ for ( let i = 0 ; i < lh . length ; ++ i ) {
925962 hitBox = lh [ i ] ;
926963
927964 if ( _isBetween ( x , hitBox . left , hitBox . left + hitBox . width )
928965 && _isBetween ( y , hitBox . top , hitBox . top + hitBox . height ) ) {
929966 // Touching an element
930- return this . navigation . legendItems [ i ] ;
967+ return legendItems [ i ] ;
931968 }
932969 }
933970 }
@@ -939,20 +976,25 @@ export class Legend extends Element {
939976 * @private
940977 */
941978 _handleNavigationEvent ( e ) {
942- if ( e . type === 'click' ) {
943- const dir = this . _getNavigationDirAt ( e . x , e . y ) ;
944- if ( dir ) {
945- const { page, totalPages} = this . navigation ;
946- const lastPage = totalPages - 1 ;
947- const newPage = this . navigation . page = Math . max ( 0 , Math . min ( lastPage , this . navigation . page + dir ) ) ;
948-
949- if ( newPage !== page ) {
950- this . buildNavigation ( ) ;
951- this . fit ( ) ;
952- this . adjustHitBoxes ( ) ;
953- this . chart . render ( ) ;
954- }
955- }
979+ if ( ! this . navigation || this . navigation . totalPages < 2 || e . type !== 'click' ) {
980+ return ;
981+ }
982+
983+ const dir = this . _getNavigationDirAt ( e . x , e . y ) ;
984+
985+ if ( ! dir ) {
986+ return ;
987+ }
988+
989+ const { page, totalPages} = this . navigation ;
990+ const lastPage = totalPages - 1 ;
991+ const newPage = this . navigation . page = Math . max ( 0 , Math . min ( lastPage , this . navigation . page + dir ) ) ;
992+
993+ if ( newPage !== page ) {
994+ this . buildNavigation ( ) ;
995+ this . fit ( ) ;
996+ this . adjustHitBoxes ( ) ;
997+ this . chart . render ( ) ;
956998 }
957999 }
9581000
@@ -961,9 +1003,7 @@ export class Legend extends Element {
9611003 * @param {ChartEvent } e - The event to handle
9621004 */
9631005 handleEvent ( e ) {
964- if ( this . navigation . totalPages > 1 ) {
965- this . _handleNavigationEvent ( e ) ;
966- }
1006+ this . _handleNavigationEvent ( e ) ;
9671007
9681008 const opts = this . options ;
9691009 if ( ! isListened ( e . type , opts ) ) {
0 commit comments