@@ -40,9 +40,11 @@ const createView = props => {
40
40
41
41
const cols = ( paneIndex ) => ( row , rowIndex ) => {
42
42
const col = row . columns [ paneIndex ] || { } ;
43
- const selected = props . selectedIndex === rowIndex ;
44
43
const colIcon = col . icon ? h ( Icon , col . icon ) : null ;
45
44
const children = [ h ( 'span' , { } , [ typeof col === 'object' ? col . label : col ] ) ] ;
45
+ const selected = props . multiselect
46
+ ? props . selectedIndex . indexOf ( rowIndex ) !== - 1
47
+ : props . selectedIndex === rowIndex ;
46
48
47
49
if ( colIcon ) {
48
50
children . unshift ( colIcon ) ;
@@ -52,11 +54,11 @@ const createView = props => {
52
54
key : row . key ,
53
55
'data-has-icon' : col . icon ? true : undefined ,
54
56
class : 'osjs-gui-list-view-cell' + ( selected ? ' osjs__active' : '' ) ,
55
- ontouchstart : ( ev ) => tapper ( ev , ( ) => props . onactivate ( { data : row . data , index : rowIndex , ev} ) ) ,
56
- ondblclick : ( ev ) => props . onactivate ( { data : row . data , index : rowIndex , ev} ) ,
57
- onclick : ( ev ) => props . onselect ( { data : row . data , index : rowIndex , ev} ) ,
58
- oncontextmenu : ( ev ) => props . oncontextmenu ( { data : row . data , index : rowIndex , ev} ) ,
59
- oncreate : ( el ) => props . oncreate ( { data : row . data , index : rowIndex , el} )
57
+ ontouchstart : ( ev ) => tapper ( ev , ( ) => props . onactivate ( { index : rowIndex , ev} ) ) ,
58
+ ondblclick : ( ev ) => props . onactivate ( { index : rowIndex , ev} ) ,
59
+ onclick : ( ev ) => props . onselect ( { index : rowIndex , ev} ) ,
60
+ oncontextmenu : ( ev ) => props . oncontextmenu ( { index : rowIndex , ev} ) ,
61
+ oncreate : ( el ) => props . oncreate ( { index : rowIndex , el} )
60
62
} , children ) ;
61
63
} ;
62
64
@@ -86,7 +88,11 @@ const createView = props => {
86
88
} ,
87
89
oncreate : el => ( el . scrollTop = props . scrollTop ) ,
88
90
onupdate : el => {
89
- if ( props . selectedIndex < 0 ) {
91
+ const notSelected = props . multiselect
92
+ ? props . selectedIndex . length === 0
93
+ : props . selectedIndex < 0 ;
94
+
95
+ if ( notSelected ) {
90
96
el . scrollTop = props . scrollTop ;
91
97
}
92
98
}
@@ -99,25 +105,101 @@ export const ListView = props => h(Element, Object.assign({
99
105
100
106
export const listView = ( {
101
107
component : ( state , actions ) => {
108
+ const createSelection = index => {
109
+ if ( state . multiselect ) {
110
+ const foundIndex = state . selectedIndex . indexOf ( index ) ;
111
+ const newSelection = [ ...state . selectedIndex ] ;
112
+ if ( foundIndex === - 1 ) {
113
+ newSelection . push ( index ) ;
114
+ } else {
115
+ newSelection . splice ( foundIndex , 1 ) ;
116
+ }
117
+
118
+ return newSelection ;
119
+ }
120
+
121
+ return state . selectedIndex ;
122
+ } ;
123
+
124
+ /**
125
+ * Creates a range of indexes from start to end
126
+ * @param {Number } start
127
+ * @param {Number } end
128
+ * @return {Array }
129
+ */
130
+ const createSelectionRange = ( start , end ) => {
131
+ // Swaps start and end if start is greater than end
132
+ if ( start > end ) {
133
+ [ start , end ] = [ end , start ] ;
134
+ }
135
+
136
+ const indices = [
137
+ ...state . selectedIndex ,
138
+ // Generates a range of indexes from start to end
139
+ ...Array . from ( { length : end - start + 1 } , ( _ , i ) => i + start )
140
+ ] ;
141
+
142
+ // Remove duplicates from the array
143
+ return [ ...new Set ( indices ) ] ;
144
+ } ;
145
+
146
+ const getSelection = ( index , ev ) => {
147
+ const selected = state . multiselect
148
+ ? ( ev . shiftKey
149
+ ? createSelectionRange ( state . previousSelectedIndex , index )
150
+ : ev . ctrlKey
151
+ ? createSelection ( index )
152
+ : [ index ] )
153
+ : index ;
154
+
155
+ const data = state . multiselect
156
+ ? selected . map ( ( item ) => state . rows [ item ] . data )
157
+ : state . rows [ selected ] . data ;
158
+
159
+ // Store the previous index in the state to use for calculating the
160
+ // range if the shift key is pressed
161
+ if ( state . multiselect ) {
162
+ actions . setPreviousSelectedIndex ( index ) ;
163
+ }
164
+
165
+ return { selected, data} ;
166
+ } ;
167
+
168
+ const clearCurrentSelection = ( index ) => {
169
+ const selected = state . multiselect ? [ ] : - 1 ;
170
+
171
+ const data = state . multiselect
172
+ ? state . selectedIndex . map ( ( item ) => state . rows [ item ] . data )
173
+ : state . rows [ index ] . data ;
174
+
175
+ return { selected, data} ;
176
+ } ;
177
+
102
178
const newProps = Object . assign ( {
179
+ multiselect : false ,
103
180
zebra : true ,
104
181
columns : [ ] ,
105
182
rows : [ ] ,
106
- onselect : ( { data, index, ev} ) => {
107
- actions . select ( { data, index, ev} ) ;
108
- actions . setSelectedIndex ( index ) ;
183
+ onselect : ( { index, ev} ) => {
184
+ const { selected, data} = getSelection ( index , ev ) ;
185
+ actions . select ( { data, index, ev, selected} ) ;
186
+ actions . setSelectedIndex ( selected ) ;
109
187
} ,
110
- onactivate : ( { data, index, ev} ) => {
111
- actions . activate ( { data, index, ev} ) ;
112
- actions . setSelectedIndex ( - 1 ) ;
188
+ onactivate : ( { index, ev} ) => {
189
+ const { selected, data} = clearCurrentSelection ( index ) ;
190
+ actions . activate ( { data, index, ev, selected} ) ;
191
+ actions . setSelectedIndex ( selected ) ;
113
192
} ,
114
- oncontextmenu : ( { data, index, ev} ) => {
193
+ oncontextmenu : ( { index, ev} ) => {
194
+ const { selected, data} = getSelection ( index , ev ) ;
195
+
115
196
actions . select ( { data, index, ev} ) ;
116
- actions . contextmenu ( { data, index, ev} ) ;
117
- actions . setSelectedIndex ( index ) ;
197
+ actions . contextmenu ( { data, index, ev, selected } ) ;
198
+ actions . setSelectedIndex ( selected ) ;
118
199
} ,
119
- oncreate : ( args ) => {
120
- actions . created ( args ) ;
200
+ oncreate : ( { index, el} ) => {
201
+ const data = state . rows [ index ] . data ;
202
+ actions . created ( { index, el, data} ) ;
121
203
} ,
122
204
onscroll : ( ev ) => {
123
205
actions . scroll ( ev ) ;
@@ -128,7 +210,7 @@ export const listView = ({
128
210
} ,
129
211
130
212
state : state => Object . assign ( {
131
- selectedIndex : - 1 ,
213
+ selectedIndex : state . multiselect ? [ ] : - 1 ,
132
214
scrollTop : 0
133
215
} , state ) ,
134
216
@@ -141,6 +223,7 @@ export const listView = ({
141
223
setRows : rows => ( { rows} ) ,
142
224
setColumns : columns => ( { columns} ) ,
143
225
setScrollTop : scrollTop => state => ( { scrollTop} ) ,
144
- setSelectedIndex : selectedIndex => state => ( { selectedIndex} )
226
+ setSelectedIndex : selectedIndex => ( { selectedIndex} ) ,
227
+ setPreviousSelectedIndex : previousSelectedIndex => ( { previousSelectedIndex} ) ,
145
228
} , actions || { } )
146
229
} ) ;
0 commit comments