window.addEventListener('scroll', vnode.state.maybeLoadMore)
window.addEventListener('resize', vnode.state.maybeLoadMore)
vnode.state.timer = window.setInterval(vnode.state.maybeLoadMore, 200)
+ vnode.state.loader = vnode.attrs.loader
vnode.state.onupdate(vnode)
},
onupdate: function(vnode) {
window.components.collection_search = {
oninit: function(vnode) {
vnode.state.sessionDB = new window.models.SessionDB()
- vnode.state.searchEntered = m.stream('')
- vnode.state.searchStart = m.stream('')
- vnode.state.searchStart.map(function(q) {
+ vnode.state.searchEntered = m.stream()
+ vnode.state.searchActive = m.stream()
+ // When searchActive changes (e.g., when restoring state
+ // after navigation), update the text field too.
+ vnode.state.searchActive.map(vnode.state.searchEntered)
+ // When searchActive changes, create a new loader that filters
+ // with the given search term.
+ vnode.state.searchActive.map(function(q) {
vnode.state.loader = new window.models.MultisiteLoader({
loadFunc: function(session, filters) {
if (q)
var sessions = vnode.state.sessionDB.loadAll()
return m('form', {
onsubmit: function() {
- vnode.state.searchStart(vnode.state.searchEntered())
+ vnode.state.searchActive(vnode.state.searchEntered())
+ vnode.state.forgetSavedState = true
return false
},
}, [
- m('.row', [
- m('.col-md-6', [
- m('.input-group', [
- m('input#search.form-control[placeholder=Search]', {
- oninput: m.withAttr('value', vnode.state.searchEntered),
- }),
- m('.input-group-btn', [
- m('input.btn.btn-primary[type=submit][value="Search"]'),
+ m(window.components.save_state, {
+ defaultState: '',
+ currentState: vnode.state.searchActive,
+ forgetSavedState: vnode.state.forgetSavedState,
+ saveBodyHeight: true,
+ }),
+ vnode.state.loader && [
+ m('.row', [
+ m('.col-md-6', [
+ m('.input-group', [
+ m('input#search.form-control[placeholder=Search]', {
+ oninput: m.withAttr('value', vnode.state.searchEntered),
+ value: vnode.state.searchEntered(),
+ }),
+ m('.input-group-btn', [
+ m('input.btn.btn-primary[type=submit][value="Search"]'),
+ ]),
]),
]),
+ m('.col-md-6', [
+ 'Searching sites: ',
+ Object.keys(sessions).length == 0
+ ? m('span.label.label-xs.label-danger', 'none')
+ : Object.keys(sessions).sort().map(function(key) {
+ return [m('span.label.label-xs', {
+ className: !vnode.state.loader.pagers[key] ? 'label-default' :
+ vnode.state.loader.pagers[key].items() ? 'label-success' :
+ 'label-warning',
+ }, key), ' ']
+ }),
+ ' ',
+ m('a[href="/sessions"]', 'Add/remove sites'),
+ ]),
]),
- m('.col-md-6', [
- 'Searching sites: ',
- Object.keys(sessions).length == 0
- ? m('span.label.label-xs.label-danger', 'none')
- : Object.keys(sessions).sort().map(function(key) {
- return [m('span.label.label-xs', {
- className: !vnode.state.loader.pagers[key] ? 'label-default' :
- vnode.state.loader.pagers[key].items() ? 'label-success' :
- 'label-warning',
- }, key), ' ']
- }),
- ' ',
- m('a[href="/sessions"]', 'Add/remove sites'),
- ]),
- ]),
- m(window.components.collection_table, {
- loader: vnode.state.loader,
- }),
+ m(window.components.collection_table, {
+ loader: vnode.state.loader,
+ }),
+ ],
])
},
}
--- /dev/null
+// Copyright (C) The Arvados Authors. All rights reserved.
+//
+// SPDX-License-Identifier: AGPL-3.0
+
+window.components = window.components || {}
+window.components.save_state = {
+ saveState: function() {
+ var state = history.state || {}
+ state.bodyHeight = window.getComputedStyle(document.body)['height']
+ state.currentState = this.currentState()
+ history.replaceState(state, '')
+ },
+ oninit: function(vnode) {
+ vnode.state.currentState = vnode.attrs.currentState
+ var hstate = history.state || {}
+
+ if (vnode.attrs.saveBodyHeight && hstate.bodyHeight) {
+ document.body.style['min-height'] = hstate.bodyHeight
+ delete hstate.bodyHeight
+ }
+
+ if (hstate.currentState) {
+ vnode.attrs.currentState(hstate.currentState)
+ delete hstate.currentState
+ } else {
+ vnode.attrs.currentState(vnode.attrs.defaultState)
+ }
+
+ history.replaceState(hstate, '')
+ },
+ oncreate: function(vnode) {
+ vnode.state.saveState = vnode.state.saveState.bind(vnode.state)
+ window.addEventListener('beforeunload', vnode.state.saveState)
+ vnode.state.onupdate(vnode)
+ },
+ onupdate: function(vnode) {
+ if (vnode.attrs.saveBodyHeight && vnode.attrs.forgetSavedState) {
+ document.body.style['min-height'] = null
+ }
+ },
+ onremove: function(vnode) {
+ window.removeEventListener('beforeunload', vnode.state.saveState)
+ },
+ view: function(vnode) {
+ return null
+ },
+}