diff --git a/src/listcontroller.js b/src/listcontroller.js index 87530acca272aa57fe1e0ed280df6d65379d4ff7..5968d46ee5fe600bbfc518e2edd8994b773d8c3b 100644 --- a/src/listcontroller.js +++ b/src/listcontroller.js @@ -1,5 +1,7 @@ +import m from 'mithril'; import Stream from 'mithril/stream'; import { ResourceHandler } from './auth'; +import { debounce } from './utils'; export default class DatalistController { constructor(resource, query = {}, searchKeys = false, onlineSearch = true) { @@ -16,6 +18,11 @@ export default class DatalistController { // we can tell infinite scroll that the data-version has changed. this.stateCounter = Stream(0); this.refresh(); + this.debouncedSearch = debounce((search) => { + this.setSearch(search); + this.refresh(); + m.redraw(); + }, 100); } refresh() { @@ -83,10 +90,8 @@ export default class DatalistController { if (this.onlineSearch) { this.search = search; this.query.search = search; - this.refresh(); } else if (this.clientSearchKeys.length > 0) { this.search = search; - this.refresh(); } } diff --git a/src/views/selectList.js b/src/views/selectList.js index 548ac710c3973f9edec0fae09beb2d5377ae0831..6bd86623a4c5a56d152ff1a4c8c2b04509cc38e8 100644 --- a/src/views/selectList.js +++ b/src/views/selectList.js @@ -1,11 +1,10 @@ import m from 'mithril'; import Stream from 'mithril/stream'; import { - List, ListTile, Search, IconButton, Button, Shadow, Toolbar, + List, ListTile, Search, IconButton, Button, Toolbar, ToolbarTitle, } from 'polythene-mithril'; import infinite from 'mithril-infinite'; -import { debounce } from '../utils'; import { icons, BackButton, ClearButton, SearchIcon } from './elements'; @@ -22,17 +21,6 @@ class SearchField { view({ state, attrs }) { // incoming value and focus added for result list example: const value = attrs.value !== undefined ? attrs.value : state.value(); - - const ExitButton = attrs.onCancel ? { - view() { - return m(Button, { - label: 'Cancel', - className: 'blue-button', - events: { onclick: attrs.onCancel }, - }); - }, - } : 'div'; - return m(Search, Object.assign( {}, { @@ -48,12 +36,8 @@ class SearchField { defaultValue: attrs.defaultValue, }, buttons: { - none: { - after: m(ExitButton), - }, focus: { before: m(BackButton, { leave: state.leave }), - after: m(ExitButton), }, focus_dirty: { before: m(BackButton, { leave: state.leave }), @@ -64,7 +48,6 @@ class SearchField { after: m(ClearButton, { clear: state.clear }), }, }, - before: m(Shadow), }, attrs, )); @@ -82,7 +65,8 @@ export default class SelectList { } onupdate({ attrs: { selection = null } }) { - console.log(selection); + // make it possible to change the selection from outside, e.g. to set the field to an + // existing group moderator if (selection) this.selected = selection; } @@ -115,7 +99,7 @@ export default class SelectList { }, }) { return m('div', [ - this.selected ? m(Toolbar, { compact: true, style: { background: 'rgb(78, 242, 167)' } }, [ + m(Toolbar, { compact: true, style: { background: 'rgb(78, 242, 167)' } }, this.selected ? [ m(IconButton, { icon: { svg: m.trust(icons.clear) }, ink: false, @@ -139,29 +123,42 @@ export default class SelectList { }, }, }) : '', - ]) : m(SearchField, Object.assign({}, { - style: { background: 'rgb(78, 242, 167)' }, - onChange: ({ value, focus }) => { - if (focus) { - this.showList = true; - } else if (!focus) { - // don't close the list immidiately, as 'out of focus' could - // also mean that the user is clicking on a list item - setTimeout(() => { this.showList = false; m.redraw(); }, 50); - } - if (value !== this.searchValue) { - // if we always update the search value, this would also happen - // immidiately in the moment where we click on the listitem. - // Then, the list get's updated before the click is registered. - // So, we make sure this state change is due to value change and - // not due to focus change. - this.searchValue = value; - controller.setSearch(value); - setTimeout(() => { controller.refresh(); }, 500); - } - }, - onCancel, - })), + ] : [ + m(SearchField, Object.assign({}, { + style: { background: 'rgb(78, 242, 167)' }, + onChange: ({ value, focus }) => { + // onChange is called either if the value or focus fo the SearchField + // changes. + // At value change we want to update the search + // at focus changt we hie the list of results. As focus change also + // happens while clicking on an item in the list of results, the list + // is hidden after a short Timeout that has to be sufficiently long + // to register the onclick of the listitem. Can be a problem for different + // OS and browsers. + if (focus) { + this.showList = true; + } else if (!focus) { + // don't close the list immidiately, as 'out of focus' could + // also mean that the user is clicking on a list item + setTimeout(() => { this.showList = false; m.redraw(); }, 500); + } + if (value !== this.searchValue) { + // if we always update the search value, this would also happen + // immidiately in the moment where we click on the listitem. + // Then, the list get's updated before the click is registered. + // So, we make sure this state change is due to value change and + // not due to focus change. + this.searchValue = value; + controller.debouncedSearch(value); + } + }, + })), + onCancel ? m(Button, { + label: 'cancel', + className: 'blue-button', + events: { onclick: onCancel }, + }) : '', + ]), (this.showList && !this.selected) ? m(List, { style: { height: '400px', 'background-color': 'white' }, tiles: m(infinite, controller.infiniteScrollParams(this.item())), diff --git a/src/views/tableView.js b/src/views/tableView.js index 3189fa18bcd353f13921d29622bf19f1ea4edbd0..2b6805149a96a9bb14e3bfa3d4c0f0b1f696b595 100644 --- a/src/views/tableView.js +++ b/src/views/tableView.js @@ -3,7 +3,6 @@ import infinite from 'mithril-infinite'; import { List, ListTile, Toolbar, Search, Button } from 'polythene-mithril'; import 'polythene-css'; import { styler } from 'polythene-core-css'; -import { debounce } from '../utils'; const tableStyles = [ { @@ -87,10 +86,6 @@ export default class TableView { tableHeight = false, }, }) { - const updateList = debounce(() => { - controller.refresh(); - }, 500); - return m('div.tabletool', [ m(Toolbar, { className: 'toolbar', @@ -99,10 +94,7 @@ export default class TableView { m(Search, { textfield: { label: 'Search', - onChange: ({ value }) => { - controller.setSearch(value); - updateList(); - }, + onChange: ({ value }) => { controller.debouncedSearch(value); }, }, fullWidth: false, }),