@@ -6,14 +6,21 @@ const getState = (chart) => {
66}
77const setState = ( chart , updatedState ) => {
88 const originalState = getState ( chart ) ;
9- states . set ( chart , Object . assign ( { } , originalState , updatedState ) ) ;
9+ states . set (
10+ chart ,
11+ updatedState == null ? null : Object . assign ( { } , originalState , updatedState )
12+ ) ;
1013 return updatedState ;
1114}
1215
1316// Store options
1417const pluginOptions = {
18+ output : 'label' ,
19+ highlight : true ,
1520 colors : {
16- selection : "#e8eff6" , selectedElements : "#1f77b4" , unselectedElements : "#cccccc"
21+ selection : "#e8eff6" ,
22+ selected : "#1f77b4" , // Unused if backgroundColorDefault set on dataset
23+ unselected : "#cccccc"
1724 }
1825} ;
1926
@@ -36,18 +43,31 @@ export default {
3643 const axisElements = chart . getElementsAtEventForMode ( e , "index" , { intersect : false } ) ;
3744 if ( axisElements . length === 0 ) { return ; }
3845
39- // Get axis value
40- const axisIndex = chart . getElementsAtEventForMode ( e , "index" , { intersect : false } ) [ 0 ] . index ;
41- const axisValue = chart . data . labels [ axisIndex ] ;
42-
43- // Set selection origin
44- setState ( chart , {
46+ // Create state
47+ const state = {
4548 selectionXY : {
4649 drawing : true ,
47- start : { axisValue, axisIndex, x : e . offsetX , y : e . offsetY } ,
50+ start : { axisValue : null , axisIndex : null , x : e . offsetX , y : e . offsetY } ,
4851 end : { }
4952 }
50- } ) ;
53+ } ;
54+
55+ // Get axis value
56+ const output = chart ?. config ?. options ?. plugins ?. selectdrag ?. output || pluginOptions . output ;
57+ ( {
58+ 'label' : ( ) => {
59+ const axisIndex = chart . getElementsAtEventForMode ( e , "index" , { intersect : false } ) [ 0 ] . index ;
60+ state . selectionXY . start . axisIndex = axisIndex ;
61+ state . selectionXY . start . axisValue = chart . data . labels [ axisIndex ] ;
62+ } ,
63+ 'value' : ( ) => {
64+ // Get value by scale
65+ state . selectionXY . start . axisValue = chart . scales . x . getValueForPixel ( e . offsetX ) ;
66+ } ,
67+ } ) [ output ] ( ) ;
68+
69+ // Set selection origin
70+ setState ( chart , state ) ;
5171 } ) ;
5272
5373 // Draw end
@@ -59,19 +79,39 @@ export default {
5979 }
6080
6181 // Get axis value
62- const axisElements = chart . getElementsAtEventForMode ( e , "index" , { intersect : false } ) ;
63- const axisIndex = axisElements . length > 0 ? axisElements [ 0 ] . index : chart . data . labels . length - 1 ;
64- const axisValue = chart . data . labels [ axisIndex ] ;
65-
66- // Check values & set end origin
67- if ( state . selectionXY . start . axisIndex > axisIndex ) {
68- // Switch values - user has selected opposite way
69- state . selectionXY . end = JSON . parse ( JSON . stringify ( state . selectionXY . start ) ) ;
70- state . selectionXY . start = { axisValue, axisIndex, x : e . offsetX , y : e . offsetY }
71- } else {
72- // Set end origin
73- state . selectionXY . end = { axisValue, axisIndex, x : e . offsetX , y : e . offsetY } ;
74- }
82+ const output = chart ?. config ?. options ?. plugins ?. selectdrag ?. output || pluginOptions . output ;
83+ ( {
84+ 'label' : ( ) => {
85+ // Get value by label
86+ const axisElements = chart . getElementsAtEventForMode ( e , "index" , { intersect : false } ) ;
87+ const axisIndex = axisElements . length > 0 ? axisElements [ 0 ] . index : chart . data . labels . length - 1 ;
88+ const axisValue = chart . data . labels [ axisIndex ] ;
89+
90+ // Check values & set end origin
91+ if ( state . selectionXY . start . axisIndex > axisIndex ) {
92+ // Switch values - user has selected opposite way
93+ state . selectionXY . end = JSON . parse ( JSON . stringify ( state . selectionXY . start ) ) ;
94+ state . selectionXY . start = { axisValue, axisIndex, x : e . offsetX , y : e . offsetY }
95+ } else {
96+ // Set end origin
97+ state . selectionXY . end = { axisValue, axisIndex, x : e . offsetX , y : e . offsetY } ;
98+ }
99+ } ,
100+ 'value' : ( ) => {
101+ // Get value by scale
102+ const axisValue = chart . scales . x . getValueForPixel ( e . offsetX ) ;
103+
104+ // Check values & set end origin
105+ if ( state . selectionXY . start . axisValue > axisValue ) {
106+ // Switch values - user has selected opposite way
107+ state . selectionXY . end = JSON . parse ( JSON . stringify ( state . selectionXY . start ) ) ;
108+ state . selectionXY . start = { axisValue, axisIndex : null , x : e . offsetX , y : e . offsetY }
109+ } else {
110+ // Set end origin
111+ state . selectionXY . end = { axisValue, axisIndex : null , x : e . offsetX , y : e . offsetY } ;
112+ }
113+ } ,
114+ } ) [ output ] ( ) ;
75115
76116 // End drawing
77117 state . selectionXY . drawing = false ;
@@ -125,22 +165,47 @@ export default {
125165 return ;
126166 }
127167
168+ // Check if enabled
169+ const highlight = chart ?. config ?. options ?. plugins ?. selectdrag ?. highlight ;
170+ if ( highlight !== undefined && highlight == false ) { return ; }
171+
128172 // Check drawing status
129173 const state = getState ( chart ) ;
130174
175+ // Color based on output
176+ const output = chart ?. config ?. options ?. plugins ?. selectdrag ?. output || pluginOptions . output ;
177+ const colors = chart ?. config ?. options ?. plugins ?. selectdrag ?. colors || pluginOptions . colors ;
178+ const backgroundColorCallback = {
179+ 'label' : ( value , index , defaultColor ) => {
180+ // Show selected/unselected
181+ if ( index >= state . selectionXY . start ?. axisIndex && index <= state . selectionXY . end ?. axisIndex ) {
182+ return defaultColor ;
183+ } else {
184+ return colors . unselected ;
185+ }
186+ } ,
187+ 'value' : ( value , index , defaultColor ) => {
188+ // Show selected/unselected
189+ const v = value . x || value ;
190+ if ( v >= state . selectionXY . start ?. axisValue && v <= state . selectionXY . end ?. axisValue ) {
191+ return defaultColor ;
192+ } else {
193+ return colors . unselected ;
194+ }
195+ }
196+ } [ output ] ;
197+
131198 // Set highlighted
132199 chart . data . datasets = chart . data . datasets . map ( ( dataset ) => {
133- dataset . backgroundColor = chart . data . labels . map ( ( value , index ) => {
200+ dataset . backgroundColor = (
201+ output == 'value' ? dataset . data : chart . data . labels
202+ ) . map ( ( value , index ) => {
134203 if ( ! state || ! state ?. selectionXY ?. start ?. x || ! state ?. selectionXY ?. end ?. x ) {
135204 // Show default
136- return pluginOptions . colors . selectedElements ;
205+ return dataset . backgroundColorDefault || colors . selected ;
137206 } else {
138207 // Show selected/unselected
139- if ( index >= state . selectionXY . start ?. axisIndex && index <= state . selectionXY . end ?. axisIndex ) {
140- return pluginOptions . colors . selectedElements ;
141- } else {
142- return pluginOptions . colors . unselectedElements ;
143- }
208+ return backgroundColorCallback ( value , index , dataset . backgroundColorDefault || colors . selected ) ;
144209 }
145210 } ) ;
146211 return dataset ;
@@ -195,21 +260,33 @@ export default {
195260 }
196261 } ;
197262
263+ // Get output type
264+ const output = chart ?. config ?. options ?. plugins ?. selectdrag ?. output || pluginOptions . output ;
265+ const getValue = {
266+ 'label' : ( v ) => {
267+ const axisIndex = chart . data . labels . findIndex ( ( item ) => item === v ) ;
268+ return { i : axisIndex , v : chart . data . labels [ axisIndex ] } ;
269+ } ,
270+ 'value' : ( v ) => {
271+ return { i : null , v : v . x || v } ;
272+ }
273+ } [ output ] ;
274+
198275 // Set start axis
199- const startAxisIndex = chart . data . labels . findIndex ( ( item ) => item === range [ 0 ] ) ;
276+ const startValue = getValue ( range [ 0 ] ) ;
200277 state . selectionXY . start = {
201- axisValue : range [ 0 ] ,
202- axisIndex : startAxisIndex ,
203- x : chart . scales . x . getPixelForValue ( chart . data . labels [ startAxisIndex ] ) ,
278+ axisValue : startValue . v ,
279+ axisIndex : startValue . i ,
280+ x : chart . scales . x . getPixelForValue ( startValue . v ) ,
204281 y : 0
205282 }
206283
207284 // Set end axis
208- const endAxisIndex = chart . data . labels . findIndex ( ( item ) => item === range [ 1 ] ) ;
285+ const endValue = getValue ( range [ 1 ] ) ;
209286 state . selectionXY . end = {
210- axisValue : range [ 0 ] ,
211- axisIndex : endAxisIndex ,
212- x : chart . scales . x . getPixelForValue ( chart . data . labels [ endAxisIndex ] ) ,
287+ axisValue : endValue . v ,
288+ axisIndex : endValue . i ,
289+ x : chart . scales . x . getPixelForValue ( endValue . v ) ,
213290 y : chart . chartArea . height
214291 }
215292
0 commit comments