@@ -150,124 +150,169 @@ window.Widgets.Panel.Utils = {};
150
150
ns . contentMenuItem = false ;
151
151
152
152
153
- // setup the left click capability
154
- ns . selectArray = [ ] ;
153
+ // setup tracker for selection
154
+ ns . selection = {
155
+ list : [ ] , // array of data objects
156
+ ids : [ ] , // array of id's matching the data objects
157
+ ref : { } , // id reference to data object, for quick lookup of ref to list and ids
158
+ max : 2 , //posibly allow more selected items
159
+ maxAction : "last" , //add to bottom or top of array
160
+ add : function ( id , data ) {
161
+ if ( this . maxAction === "last" ) {
162
+ return this . popIn ( id , data ) ;
163
+ } else {
164
+ return this . shiftIn ( id , data ) ;
165
+ }
166
+ } ,
167
+ remove : function ( id , data ) {
168
+ const index = this . getIndexOf ( id ) ;
169
+ if ( index > - 1 ) {
170
+ this . list . splice ( index , 1 ) ;
171
+ this . ids . splice ( index , 1 ) ;
172
+ delete this . ref [ id ] ;
173
+ }
174
+ return index ;
175
+ } ,
176
+ popIn : function ( id , data ) { // add to bottom and remove first
177
+ let removedData ;
178
+ let removedId ;
179
+ if ( this . isFull ( ) ) {
180
+ removedData = this . list . shift ( ) ; //remove first item
181
+ removedId = this . ids . shift ( ) ; //remove first item
182
+ //remove reference
183
+ delete this . ref [ removedId ] ;
184
+ }
185
+ this . list . push ( data ) ; // add last item
186
+ this . ids . push ( id ) ; // add last item
187
+
188
+ //save id reference
189
+ this . ref [ id ] = {
190
+ d : this . list [ this . list . length - 1 ] ,
191
+ i : this . ids [ this . ids . length - 1 ]
192
+ } ;
193
+ return removedData ;
194
+ } ,
195
+ shiftIn : function ( id , data ) { // add to top and remove last
196
+ let removedData ;
197
+ let removedId ;
198
+ if ( this . isFull ( ) ) {
199
+ removedData = this . list . pop ( ) ; //remove last item
200
+ removedId = this . ids . pop ( ) ; //remove last item
201
+ //remove reference
202
+ delete this . ref [ removedId ] ;
203
+ }
204
+ this . list . unshift ( data ) ; // add first item
205
+ this . ids . unshift ( id ) ; // add first item
206
+ //save id reference
207
+ this . ref [ id ] = {
208
+ d : this . list [ 0 ] ,
209
+ i : this . ids [ 0 ]
210
+ } ;
211
+ return removedData ;
212
+ } ,
213
+ clear : function ( ) {
214
+ this . list = [ ] ;
215
+ this . ref = { } ;
216
+ } ,
217
+ isFull : function ( ) {
218
+ return this . ids . length === this . max ;
219
+ } ,
220
+ has : function ( id ) {
221
+ const hasRef = this . ref [ id ] ;
222
+ if ( hasRef === undefined ) {
223
+ return false ;
224
+ }
225
+ const hasId = this . ids . includes ( id ) ;
226
+ const hasData = this . list . includes ( hasRef . d ) ;
227
+
228
+ if ( hasId && hasData ) {
229
+ return true ;
230
+ } else {
231
+ console . error ( "ERROR: selection data is out of sync" ) ;
232
+ return false ;
233
+ }
234
+ } ,
235
+ count : function ( ) {
236
+ return this . ids . length ;
237
+ } ,
238
+ getFirst : function ( ) {
239
+ return this . list [ 0 ] ;
240
+ } ,
241
+ getLast : function ( ) {
242
+ if ( this . ids . length > 1 ) {
243
+ return this . list [ this . ids . length - 1 ] ;
244
+ }
245
+ return
246
+ } ,
247
+ getIndexOf : function ( id ) {
248
+ //get reference to the data object
249
+ const data = this . ref [ id ] ;
250
+ if ( data === undefined ) {
251
+ return - 1 ;
252
+ }
253
+ console . log ( "data->" , data ) ;
254
+ //get the index of the data object
255
+ return this . ids . indexOf ( data . i ) ;
256
+ }
257
+ } ;
258
+
155
259
ns . leftclick = function ( event , d ) {
156
260
console . group ( "Widgets.Panel.Utils.leftclick" ) ;
157
261
console . log ( "event->" , event ) ;
158
262
console . log ( "d->" , d ) ;
159
263
160
- // Setup the local theme
161
- if ( ! ns . theme ) {
162
- if ( ns . options . theme === 'light' ) {
163
- ns . theme = ns . options . light_theme
164
- } else {
165
- ns . theme = ns . options . dark_theme
166
- }
264
+ const selected = d3 . select ( this )
265
+ const id = d . id ;
266
+ const data = {
267
+ id : id ,
268
+ element : selected ,
269
+ data : d ,
270
+ event : event ,
167
271
}
168
272
169
- let len = ns . selectArray . length ;
170
- const selected = d3 . select ( this ) ; // can't use arrow scoping
171
- console . log ( `selected->` , selected ) ;
172
-
173
- if ( d3 . select ( this ) . classed ( 'clicked' ) ) {
174
- // Toggle-off the clicked state
175
- //
176
- console . log ( "Branch 1 - time to toggle select" ) ;
177
- console . log ( "ns.selectArray->" , ns . selectArray ) ;
178
- // 1. Pop the element from the array
179
- for ( var i = ns . selectArray . length - 1 ; i >= 0 ; i -- ) {
180
- if ( ns . selectArray [ i ] . id === selected . id ) {
181
- ns . selectArray . splice ( i , 1 ) ;
182
- }
183
- }
184
- // 2. deselect the node
185
- selected . classed ( "selected" , false ) ;
186
- selected . style ( "stroke" , "none" ) ;
187
- selected . style ( "stroke-width" , 0 ) ;
188
-
189
- }
190
- else if ( event . ctrlKey ) {
191
- // we will do a multi-select
192
- console . log ( "Branch 2 - multi select" ) ;
193
- if ( len < 2 ) {
194
- // Then Just add selected onto the end of the array, and style it
195
- //
196
- console . log ( "Branch 2.1 - multi select, just add one" ) ;
197
- console . log ( "ns.selectArray->" , ns . selectArray ) ;
198
- // 1. add the data element to the array
199
- ns . selectArray . push ( d ) ;
200
- // 2. highlight the node
201
- selected . classed ( "selected" , true ) ;
202
- selected . style ( "stroke" , ns . theme . select ) ;
203
- selected . style ( "stroke-width" , 5 ) ;
204
- } else if ( len === 2 ) {
205
- // First deselect the first in the list, then add the new one
206
- //
207
- console . log ( "Branch 2.2 - multi select, take one off" ) ;
208
- console . log ( "ns.selectArray->" , ns . selectArray ) ;
209
- // 1. We need to get and remove the first object in the select array
210
- let deselect = ns . selectArray . shift ( ) ;
211
- // 2. Get the DOM object that has to be deselected based on the id
212
- const deselected = d3 . select ( "#" + deselect . id ) ;
213
- console . log ( "multi deselect->" , deselect ) ;
214
- console . log ( "multi deselected->" , deselected ) ;
215
- // 3. Use the deselected object ref to remove the styling
216
- deselected . classed ( "selected" , false ) ;
217
- deselected . style ( "stroke" , "none" ) ;
218
- deselected . style ( "stroke-width" , 0 ) ;
219
- // 4. Add the new data element to the select array
220
- ns . selectArray . push ( d ) ;
221
- // 5. Highlight the selected node
222
- selected . classed ( "selected" , true ) ;
223
- selected . style ( "stroke" , ns . theme . select ) ;
224
- selected . style ( "stroke-width" , 5 ) ;
225
- } else {
226
- console . log ( "ERORR: multi-select array is broken, too many items" , ) ;
227
- ns . selectArray . length = 0 ;
228
- }
229
-
273
+ const isAlreadySelected = ns . selection . has ( id ) ;
274
+
275
+ console . log ( "isAlreadySelected->" , isAlreadySelected ) ;
276
+
277
+ //unselect me if already selected
278
+ if ( isAlreadySelected ) {
279
+ ns . selection . remove ( id , data ) ;
280
+ selected . classed ( "select-source" , false ) ;
281
+ selected . classed ( "select-target" , false ) ;
282
+ selected . classed ( "select-other" , false ) ;
230
283
} else {
231
- // we will do a single select
232
- console . log ( "Branch 3 - single select" ) ;
233
- if ( len === 0 ) {
234
- // Then Just add selected onto the end of the array, and style it
235
- //
236
- console . log ( "Branch 3.1 - Just add the new one" ) ;
237
- console . log ( "ns.selectArray->" , ns . selectArray ) ;
238
- // 1. add the data element to the array
239
- ns . selectArray . push ( d ) ;
240
- // 2. highlight the node
241
- selected . classed ( "selected" , true ) ;
242
- selected . style ( "stroke" , ns . theme . select ) ;
243
- selected . style ( "stroke-width" , 5 ) ;
244
- } else {
245
- // Deselect all in the list, then add the new one
246
- //
247
- console . log ( "Branch 3.2 - Deselect everything in the list, empty it, and then just add the new one" ) ;
248
- console . log ( "ns.selectArray->" , ns . selectArray ) ;
249
- // 1. Deselect each object in the array
250
- ns . selectArray . forEach ( ( item , index ) => {
251
- // 2. Get the DOM object that has to be deselected based on the id
252
- const deselected = d3 . select ( "#" + item . id ) ;
253
- console . log ( "single deselect->" , item ) ;
254
- console . log ( "single deselected->" , deselected ) ;
255
- // 3. Use the deselected object ref to remove the styling
256
- deselected . classed ( "selected" , false ) ;
257
- deselected . style ( "stroke" , "none" ) ;
258
- deselected . style ( "stroke-width" , 0 ) ;
259
-
260
- } ) ;
261
- // 2. Make the List Empty
262
- ns . selectArray . length = 0 ;
263
- // 3. add the new data element to the array
264
- ns . selectArray . push ( d ) ;
265
- // 5. Highlight the newly selected node
266
- selected . classed ( "selected" , true ) ;
267
- selected . style ( "stroke" , ns . theme . select ) ;
268
- selected . style ( "stroke-width" , 5 ) ;
284
+ //add me to selection and get back anything that was removed
285
+ const removedData = ns . selection . add ( id , data ) ;
286
+ // if we have removed data, then we need to deselect it
287
+ const removedId = removedData ? removedData . id : null ;
288
+ if ( removedId !== null ) {
289
+ const removedElement = removedData . element ;
290
+ removedElement . classed ( "select-source" , false ) ;
291
+ removedElement . classed ( "select-target" , false ) ;
292
+ removedElement . classed ( "select-other" , false ) ;
269
293
}
270
294
}
295
+
296
+ //highlight the first item
297
+ const firstItem = ns . selection . getFirst ( ) ;
298
+ console . log ( "firstItem->" , firstItem ) ;
299
+ if ( firstItem ) {
300
+ const firstElement = firstItem . element ;
301
+ firstElement . classed ( "select-source" , true ) ;
302
+ firstElement . classed ( "select-target" , false ) ;
303
+ firstElement . classed ( "select-other" , false ) ;
304
+ }
305
+
306
+ //highlight the last item
307
+ const lastItem = ns . selection . getLast ( ) ;
308
+ console . log ( "lastItem->" , lastItem ) ;
309
+ if ( lastItem ) {
310
+ const lastElement = lastItem . element ;
311
+ lastElement . classed ( "select-source" , false ) ;
312
+ lastElement . classed ( "select-target" , true ) ;
313
+ lastElement . classed ( "select-other" , false ) ;
314
+ }
315
+
271
316
console . groupEnd ( ) ;
272
317
}
273
318
0 commit comments