From 3d6b861627dd0aa2a90c3b0dafb4bd616bdd6d89 Mon Sep 17 00:00:00 2001 From: Anders Evenrud Date: Fri, 3 Jul 2020 01:07:53 +0200 Subject: [PATCH] Added multiselect to ListView (#32) --- src/components/ListView.js | 83 ++++++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/src/components/ListView.js b/src/components/ListView.js index adf3a03..68ae01c 100644 --- a/src/components/ListView.js +++ b/src/components/ListView.js @@ -39,9 +39,11 @@ const createView = props => { const cols = (paneIndex) => (row, rowIndex) => { const col = row.columns[paneIndex] || {}; - const selected = props.selectedIndex === rowIndex; const colIcon = col.icon ? h(Icon, col.icon) : null; const children = [h('span', {}, [typeof col === 'object' ? col.label : col])]; + const selected = props.multiselect + ? props.selectedIndex.indexOf(rowIndex) !== -1 + : props.selectedIndex === rowIndex; if (colIcon) { children.unshift(colIcon); @@ -51,11 +53,11 @@ const createView = props => { key: row.key, 'data-has-icon': col.icon ? true : undefined, class: 'osjs-gui-list-view-cell' + (selected ? ' osjs__active' : ''), - ontouchstart: (ev) => tapper(ev, () => props.onactivate({data: row.data, index: rowIndex, ev})), - ondblclick: (ev) => props.onactivate({data: row.data, index: rowIndex, ev}), - onclick: (ev) => props.onselect({data: row.data, index: rowIndex, ev}), - oncontextmenu: (ev) => props.oncontextmenu({data: row.data, index: rowIndex, ev}), - oncreate: (el) => props.oncreate({data: row.data, index: rowIndex, el}) + ontouchstart: (ev) => tapper(ev, () => props.onactivate({index: rowIndex, ev})), + ondblclick: (ev) => props.onactivate({index: rowIndex, ev}), + onclick: (ev) => props.onselect({index: rowIndex, ev}), + oncontextmenu: (ev) => props.oncontextmenu({index: rowIndex, ev}), + oncreate: (el) => props.oncreate({index: rowIndex, el}) }, children); }; @@ -79,7 +81,11 @@ const createView = props => { class: 'osjs-gui-list-view-wrapper', oncreate: el => (el.scrollTop = props.scrollTop), onupdate: el => { - if (props.selectedIndex < 0) { + const notSelected = props.multiselect + ? props.selectedIndex.length === 0 + : props.selectedIndex < 0; + + if (notSelected) { el.scrollTop = props.scrollTop; } } @@ -92,25 +98,60 @@ export const ListView = props => h(Element, Object.assign({ export const listView = ({ component: (state, actions) => { + + const createSelection = index => state.selectedIndex.indexOf(index) === -1 + ? [...state.selectedIndex, index] + : state.selectedIndex; + + const getSelection = (index, ev) => { + const selected = state.multiselect + ? (ev.shiftKey ? createSelection(index) : [index]) + : index; + + const data = state.multiselect + ? selected.map(i => state.rows[i].data) + : state.rows[selected].data; + + return {selected, data}; + }; + + const clearCurrentSelection = (index, ev) => { + const selected = state.multiselect + ? [] + : -1; + + const data = state.multiselect + ? state.selectedIndex.map(i => state.rows[i].data) + : state.rows[index].data; + + return {selected, data}; + }; + const newProps = Object.assign({ + multiselect: false, zebra: true, columns: [], rows: [], - onselect: ({data, index, ev}) => { - actions.select({data, index, ev}); - actions.setSelectedIndex(index); + onselect: ({index, ev}) => { + const {selected, data} = getSelection(index, ev); + actions.select({data, index, ev, selected}); + actions.setSelectedIndex(selected); }, - onactivate: ({data, index, ev}) => { - actions.activate({data, index, ev}); - actions.setSelectedIndex(-1); + onactivate: ({index, ev}) => { + const {selected, data} = clearCurrentSelection(index, ev); + actions.activate({data, index, ev, selected}); + actions.setSelectedIndex(selected); }, - oncontextmenu: ({data, index, ev}) => { + oncontextmenu: ({index, ev}) => { + const {selected, data} = getSelection(index, ev); + actions.select({data, index, ev}); - actions.contextmenu({data, index, ev}); - actions.setSelectedIndex(index); + actions.contextmenu({data, index, ev, selected}); + actions.setSelectedIndex(selected); }, - oncreate: (args) => { - actions.created(args); + oncreate: ({index, el}) => { + const data = state.rows[index].data; + actions.created({index, el, data}); } }, state); @@ -118,7 +159,7 @@ export const listView = ({ }, state: state => Object.assign({ - selectedIndex: -1, + selectedIndex: state.multiselect ? [] : -1, scrollTop: 0 }, state), @@ -129,7 +170,7 @@ export const listView = ({ created: () => () => ({}), setRows: rows => ({rows}), setColumns: columns => ({columns}), - setScrollTop: scrollTop => state => ({scrollTop}), - setSelectedIndex: selectedIndex => state => ({selectedIndex}) + setScrollTop: scrollTop => ({scrollTop}), + setSelectedIndex: selectedIndex => ({selectedIndex}) }, actions || {}) });