diff --git a/client/css/post-list-view.styl b/client/css/post-list-view.styl
index b266ca1..f8da90a 100644
--- a/client/css/post-list-view.styl
+++ b/client/css/post-list-view.styl
@@ -127,6 +127,11 @@
.start-tagging,
.stop-tagging
display: none
+ .masstag-hint
+ display: none
+ &.active
+ .open-masstag
+ display: none
.safety
margin-right: 0.25em
diff --git a/client/html/posts_header.tpl b/client/html/posts_header.tpl
index 5b4f1d4..e34f061 100644
--- a/client/html/posts_header.tpl
+++ b/client/html/posts_header.tpl
@@ -12,11 +12,8 @@
%><% if (ctx.canMassTag) { %><%
%><%
%><%
- %><% if (ctx.parameters.tag) { %><%
- %>Tagging with:<%
- %><% } else { %><%
- %>Mass tag<%
- %><% } %><%
+ %>Tagging with:<%
+ %>Mass tag<%
%><%
%><%= ctx.makeTextInput({name: 'masstag', value: ctx.parameters.tag}) %><%
%><%
diff --git a/client/js/controllers/comments_controller.js b/client/js/controllers/comments_controller.js
index 1758393..da76009 100644
--- a/client/js/controllers/comments_controller.js
+++ b/client/js/controllers/comments_controller.js
@@ -22,7 +22,8 @@ class CommentsController {
topNavigation.activate('comments');
topNavigation.setTitle('Listing comments');
- this._pageController = new PageController({
+ this._pageController = new PageController();
+ this._pageController.run({
parameters: ctx.parameters,
getClientUrlForPage: page => {
const parameters = Object.assign(
diff --git a/client/js/controllers/page_controller.js b/client/js/controllers/page_controller.js
index 6a490ee..6f86e0c 100644
--- a/client/js/controllers/page_controller.js
+++ b/client/js/controllers/page_controller.js
@@ -6,19 +6,25 @@ const ManualPageView = require('../views/manual_page_view.js');
class PageController {
constructor(ctx) {
+ if (settings.get().endlessScroll) {
+ this._view = new EndlessPageView();
+ } else {
+ this._view = new ManualPageView();
+ }
+ }
+
+ get view() {
+ return this._view;
+ }
+
+ run(ctx) {
const extendedContext = {
getClientUrlForPage: ctx.getClientUrlForPage,
parameters: ctx.parameters,
};
- ctx.headerContext = Object.assign({}, extendedContext);
ctx.pageContext = Object.assign({}, extendedContext);
-
- if (settings.get().endlessScroll) {
- this._view = new EndlessPageView(ctx);
- } else {
- this._view = new ManualPageView(ctx);
- }
+ this._view.run(ctx);
}
showSuccess(message) {
diff --git a/client/js/controllers/post_list_controller.js b/client/js/controllers/post_list_controller.js
index 00da59d..c1dfd06 100644
--- a/client/js/controllers/post_list_controller.js
+++ b/client/js/controllers/post_list_controller.js
@@ -26,37 +26,18 @@ class PostListController {
topNavigation.setTitle('Listing posts');
this._ctx = ctx;
- this._pageController = new PageController({
+ this._pageController = new PageController();
+
+ this._headerView = new PostsHeaderView({
+ hostNode: this._pageController.view.pageHeaderHolderNode,
parameters: ctx.parameters,
- getClientUrlForPage: page => {
- const parameters = Object.assign(
- {}, ctx.parameters, {page: page});
- return '/posts/' + misc.formatUrlParameters(parameters);
- },
- requestPage: page => {
- return PostList.search(
- this._decorateSearchQuery(ctx.parameters.query),
- page, settings.get().postsPerPage, fields);
- },
- headerRenderer: headerCtx => {
- Object.assign(headerCtx, {
- canMassTag: api.hasPrivilege('tags:masstag'),
- massTagTags: this._massTagTags,
- });
- return new PostsHeaderView(headerCtx);
- },
- pageRenderer: pageCtx => {
- Object.assign(pageCtx, {
- canViewPosts: api.hasPrivilege('posts:view'),
- canMassTag: api.hasPrivilege('tags:masstag'),
- massTagTags: this._massTagTags,
- });
- const view = new PostsPageView(pageCtx);
- view.addEventListener('tag', e => this._evtTag(e));
- view.addEventListener('untag', e => this._evtUntag(e));
- return view;
- },
+ canMassTag: api.hasPrivilege('tags:masstag'),
+ massTagTags: this._massTagTags,
});
+ this._headerView.addEventListener(
+ 'navigate', e => this._evtNavigate(e));
+
+ this._syncPageController();
}
showSuccess(message) {
@@ -67,6 +48,15 @@ class PostListController {
return (this._ctx.parameters.tag || '').split(/\s+/).filter(s => s);
}
+ _evtNavigate(e) {
+ history.pushState(
+ null,
+ window.title,
+ '/posts/' + misc.formatUrlParameters(e.detail.parameters));
+ Object.assign(this._ctx.parameters, e.detail.parameters);
+ this._syncPageController();
+ }
+
_evtTag(e) {
for (let tag of this._massTagTags) {
e.detail.post.addTag(tag);
@@ -100,6 +90,32 @@ class PostListController {
}
return text.trim();
}
+
+ _syncPageController() {
+ this._pageController.run({
+ parameters: this._ctx.parameters,
+ getClientUrlForPage: page => {
+ return '/posts/' + misc.formatUrlParameters(
+ Object.assign({}, this._ctx.parameters, {page: page}));
+ },
+ requestPage: page => {
+ return PostList.search(
+ this._decorateSearchQuery(this._ctx.parameters.query),
+ page, settings.get().postsPerPage, fields);
+ },
+ pageRenderer: pageCtx => {
+ Object.assign(pageCtx, {
+ canViewPosts: api.hasPrivilege('posts:view'),
+ canMassTag: api.hasPrivilege('tags:masstag'),
+ massTagTags: this._massTagTags,
+ });
+ const view = new PostsPageView(pageCtx);
+ view.addEventListener('tag', e => this._evtTag(e));
+ view.addEventListener('untag', e => this._evtUntag(e));
+ return view;
+ },
+ });
+ }
}
module.exports = router => {
diff --git a/client/js/controllers/snapshots_controller.js b/client/js/controllers/snapshots_controller.js
index 1cc853d..3aa3f89 100644
--- a/client/js/controllers/snapshots_controller.js
+++ b/client/js/controllers/snapshots_controller.js
@@ -19,7 +19,8 @@ class SnapshotsController {
topNavigation.activate('');
topNavigation.setTitle('History');
- this._pageController = new PageController({
+ this._pageController = new PageController();
+ this._pageController.run({
parameters: ctx.parameters,
getClientUrlForPage: page => {
const parameters = Object.assign(
diff --git a/client/js/controllers/tag_list_controller.js b/client/js/controllers/tag_list_controller.js
index 0cc11a2..0f1f00e 100644
--- a/client/js/controllers/tag_list_controller.js
+++ b/client/js/controllers/tag_list_controller.js
@@ -23,27 +23,18 @@ class TagListController {
topNavigation.activate('tags');
topNavigation.setTitle('Listing tags');
- this._pageController = new PageController({
+ this._ctx = ctx;
+ this._pageController = new PageController();
+
+ this._headerView = new TagsHeaderView({
+ hostNode: this._pageController.view.pageHeaderHolderNode,
parameters: ctx.parameters,
- getClientUrlForPage: page => {
- const parameters = Object.assign(
- {}, ctx.parameters, {page: page});
- return '/tags/' + misc.formatUrlParameters(parameters);
- },
- requestPage: page => {
- return TagList.search(ctx.parameters.query, page, 50, fields);
- },
- headerRenderer: headerCtx => {
- Object.assign(headerCtx, {
- canEditTagCategories:
- api.hasPrivilege('tagCategories:edit'),
- });
- return new TagsHeaderView(headerCtx);
- },
- pageRenderer: pageCtx => {
- return new TagsPageView(pageCtx);
- },
+ canEditTagCategories: api.hasPrivilege('tagCategories:edit'),
});
+ this._headerView.addEventListener(
+ 'navigate', e => this._evtNavigate(e));
+
+ this._syncPageController();
}
showSuccess(message) {
@@ -53,6 +44,33 @@ class TagListController {
showError(message) {
this._pageController.showError(message);
}
+
+ _evtNavigate(e) {
+ history.pushState(
+ null,
+ window.title,
+ '/tags/' + misc.formatUrlParameters(e.detail.parameters));
+ Object.assign(this._ctx.parameters, e.detail.parameters);
+ this._syncPageController();
+ }
+
+ _syncPageController() {
+ this._pageController.run({
+ parameters: this._ctx.parameters,
+ getClientUrlForPage: page => {
+ const parameters = Object.assign(
+ {}, this._ctx.parameters, {page: page});
+ return '/tags/' + misc.formatUrlParameters(parameters);
+ },
+ requestPage: page => {
+ return TagList.search(
+ this._ctx.parameters.query, page, 50, fields);
+ },
+ pageRenderer: pageCtx => {
+ return new TagsPageView(pageCtx);
+ },
+ });
+ }
}
module.exports = router => {
diff --git a/client/js/controllers/user_list_controller.js b/client/js/controllers/user_list_controller.js
index 9cdd0a1..6e44ce8 100644
--- a/client/js/controllers/user_list_controller.js
+++ b/client/js/controllers/user_list_controller.js
@@ -20,18 +20,42 @@ class UserListController {
topNavigation.activate('users');
topNavigation.setTitle('Listing users');
- this._pageController = new PageController({
+ this._ctx = ctx;
+ this._pageController = new PageController();
+
+ this._headerView = new UsersHeaderView({
+ hostNode: this._pageController.view.pageHeaderHolderNode,
parameters: ctx.parameters,
+ });
+ this._headerView.addEventListener(
+ 'navigate', e => this._evtNavigate(e));
+
+ this._syncPageController();
+ }
+
+ showSuccess(message) {
+ this._pageController.showSuccess(message);
+ }
+
+ _evtNavigate(e) {
+ history.pushState(
+ null,
+ window.title,
+ '/users/' + misc.formatUrlParameters(e.detail.parameters));
+ Object.assign(this._ctx.parameters, e.detail.parameters);
+ this._syncPageController();
+ }
+
+ _syncPageController() {
+ this._pageController.run({
+ parameters: this._ctx.parameters,
getClientUrlForPage: page => {
const parameters = Object.assign(
- {}, ctx.parameters, {page: page});
+ {}, this._ctx.parameters, {page: page});
return '/users/' + misc.formatUrlParameters(parameters);
},
requestPage: page => {
- return UserList.search(ctx.parameters.query, page);
- },
- headerRenderer: headerCtx => {
- return new UsersHeaderView(headerCtx);
+ return UserList.search(this._ctx.parameters.query, page);
},
pageRenderer: pageCtx => {
Object.assign(pageCtx, {
@@ -41,10 +65,6 @@ class UserListController {
},
});
}
-
- showSuccess(message) {
- this._pageController.showSuccess(message);
- }
}
module.exports = router => {
diff --git a/client/js/router.js b/client/js/router.js
index 2226059..f757e07 100644
--- a/client/js/router.js
+++ b/client/js/router.js
@@ -137,8 +137,8 @@ class Router {
}
show(path, state, push) {
- const oldPath = this.ctx ? this.ctx.path : ctx.path;
const ctx = new Context(path, state);
+ const oldPath = this.ctx ? this.ctx.path : ctx.path;
this.dispatch(ctx, () => {
if (ctx.path !== oldPath && push !== false) {
ctx.pushState();
diff --git a/client/js/util/search.js b/client/js/util/search.js
new file mode 100644
index 0000000..ba5c2f7
--- /dev/null
+++ b/client/js/util/search.js
@@ -0,0 +1,17 @@
+'use strict';
+
+const misc = require('./misc.js');
+const keyboard = require('../util/keyboard.js');
+const views = require('./views.js');
+
+function searchInputNodeFocusHelper(inputNode) {
+ keyboard.bind('q', () => {
+ inputNode.focus();
+ inputNode.setSelectionRange(
+ inputNode.value.length, inputNode.value.length);
+ });
+}
+
+module.exports = misc.arrayToObject([
+ searchInputNodeFocusHelper,
+], func => func.name);
diff --git a/client/js/util/views.js b/client/js/util/views.js
index f340a00..c25a505 100644
--- a/client/js/util/views.js
+++ b/client/js/util/views.js
@@ -248,6 +248,25 @@ function makeVoidElement(name, attributes) {
return `<${_serializeElement(name, attributes)}/>`;
}
+function emptyContent(target) {
+ while (target.lastChild) {
+ target.removeChild(target.lastChild);
+ }
+}
+
+function replaceContent(target, source) {
+ emptyContent(target);
+ if (source instanceof NodeList) {
+ for (let child of [...source]) {
+ target.appendChild(child);
+ }
+ } else if (source instanceof Node) {
+ target.appendChild(source);
+ } else if (source !== null) {
+ throw `Invalid view source: ${source}`;
+ }
+}
+
function showMessage(target, message, className) {
if (!message) {
message = 'Unknown message';
@@ -283,9 +302,7 @@ function showInfo(target, message) {
function clearMessages(target) {
const messagesHolder = target.querySelector('.messages');
/* TODO: animate that */
- while (messagesHolder.lastChild) {
- messagesHolder.removeChild(messagesHolder.lastChild);
- }
+ emptyContent(messagesHolder);
}
function htmlToDom(html) {
@@ -394,25 +411,10 @@ function enableForm(form) {
}
}
-function replaceContent(target, source) {
- while (target.lastChild) {
- target.removeChild(target.lastChild);
- }
- if (source instanceof NodeList) {
- for (let child of [...source]) {
- target.appendChild(child);
- }
- } else if (source instanceof Node) {
- target.appendChild(source);
- } else if (source !== null) {
- throw `Invalid view source: ${source}`;
- }
-}
-
function syncScrollPosition() {
window.requestAnimationFrame(
() => {
- if (history.state.hasOwnProperty('scrollX')) {
+ if (history.state && history.state.hasOwnProperty('scrollX')) {
window.scrollTo(history.state.scrollX, history.state.scrollY);
} else {
window.scrollTo(0, 0);
@@ -488,6 +490,7 @@ document.addEventListener('click', e => {
module.exports = misc.arrayToObject([
htmlToDom,
getTemplate,
+ emptyContent,
replaceContent,
enableForm,
disableForm,
diff --git a/client/js/views/endless_page_view.js b/client/js/views/endless_page_view.js
index 2728047..6e6787f 100644
--- a/client/js/views/endless_page_view.js
+++ b/client/js/views/endless_page_view.js
@@ -9,27 +9,22 @@ const pageTemplate = views.getTemplate('endless-pager-page');
class EndlessPageView {
constructor(ctx) {
this._hostNode = document.getElementById('content-holder');
+ views.replaceContent(this._hostNode, holderTemplate());
+ }
+
+ run(ctx) {
this._active = true;
this._working = 0;
this._init = false;
+ views.emptyContent(this._pagesHolderNode);
+
this.threshold = window.innerHeight / 3;
this.minPageShown = null;
this.maxPageShown = null;
this.totalPages = null;
this.currentPage = null;
- const sourceNode = holderTemplate();
- const pageHeaderHolderNode
- = sourceNode.querySelector('.page-header-holder');
- this._pagesHolderNode = sourceNode.querySelector('.pages-holder');
- views.replaceContent(this._hostNode, sourceNode);
-
- ctx.headerContext.hostNode = pageHeaderHolderNode;
- if (ctx.headerRenderer) {
- ctx.headerRenderer(ctx.headerContext);
- }
-
this._loadPage(ctx, ctx.parameters.page, true).then(pageNode => {
if (ctx.parameters.page !== 1) {
pageNode.scrollIntoView();
@@ -40,6 +35,14 @@ class EndlessPageView {
views.monitorNodeRemoval(this._pagesHolderNode, () => this._destroy());
}
+ get pageHeaderHolderNode() {
+ return this._hostNode.querySelector('.page-header-holder');
+ }
+
+ get _pagesHolderNode() {
+ return this._hostNode.querySelector('.pages-holder');
+ }
+
_destroy() {
this._active = false;
}
diff --git a/client/js/views/manual_page_view.js b/client/js/views/manual_page_view.js
index c4ce34f..3507fd7 100644
--- a/client/js/views/manual_page_view.js
+++ b/client/js/views/manual_page_view.js
@@ -56,25 +56,17 @@ function _getPages(currentPage, pageNumbers, ctx) {
class ManualPageView {
constructor(ctx) {
this._hostNode = document.getElementById('content-holder');
+ views.replaceContent(this._hostNode, holderTemplate());
+ }
- const sourceNode = holderTemplate();
- const pageContentHolderNode
- = sourceNode.querySelector('.page-content-holder');
- const pageHeaderHolderNode
- = sourceNode.querySelector('.page-header-holder');
- const pageNavNode = sourceNode.querySelector('.page-nav');
+ run(ctx) {
const currentPage = ctx.parameters.page;
-
- ctx.headerContext.hostNode = pageHeaderHolderNode;
- if (ctx.headerRenderer) {
- ctx.headerRenderer(ctx.headerContext);
- }
-
- views.replaceContent(this._hostNode, sourceNode);
+ this.clearMessages();
+ views.emptyContent(this._pageNavNode);
ctx.requestPage(currentPage).then(response => {
Object.assign(ctx.pageContext, response);
- ctx.pageContext.hostNode = pageContentHolderNode;
+ ctx.pageContext.hostNode = this._pageContentHolderNode;
ctx.pageRenderer(ctx.pageContext);
const totalPages = Math.ceil(response.total / response.pageSize);
@@ -94,7 +86,7 @@ class ManualPageView {
if (response.total) {
views.replaceContent(
- pageNavNode,
+ this._pageNavNode,
navTemplate({
prevLink: ctx.getClientUrlForPage(currentPage - 1),
nextLink: ctx.getClientUrlForPage(currentPage + 1),
@@ -114,6 +106,22 @@ class ManualPageView {
});
}
+ get pageHeaderHolderNode() {
+ return this._hostNode.querySelector('.page-header-holder');
+ }
+
+ get _pageContentHolderNode() {
+ return this._hostNode.querySelector('.page-content-holder');
+ }
+
+ get _pageNavNode() {
+ return this._hostNode.querySelector('.page-nav');
+ }
+
+ clearMessages() {
+ views.clearMessages(this._hostNode);
+ }
+
showSuccess(message) {
views.showSuccess(this._hostNode, message);
}
diff --git a/client/js/views/posts_header_view.js b/client/js/views/posts_header_view.js
index 649ed46..07f3fe0 100644
--- a/client/js/views/posts_header_view.js
+++ b/client/js/views/posts_header_view.js
@@ -1,41 +1,34 @@
'use strict';
-const router = require('../router.js');
+const events = require('../events.js');
const settings = require('../models/settings.js');
const keyboard = require('../util/keyboard.js');
const misc = require('../util/misc.js');
+const search = require('../util/search.js');
const views = require('../util/views.js');
const TagAutoCompleteControl =
require('../controls/tag_auto_complete_control.js');
const template = views.getTemplate('posts-header');
-class PostsHeaderView {
+class PostsHeaderView extends events.EventTarget {
constructor(ctx) {
+ super();
+
ctx.settings = settings.get();
this._ctx = ctx;
this._hostNode = ctx.hostNode;
views.replaceContent(this._hostNode, template(ctx));
- if (this._queryInputNode) {
- new TagAutoCompleteControl(this._queryInputNode, {addSpace: true});
- }
+ this._queryAutoCompleteControl = new TagAutoCompleteControl(
+ this._queryInputNode, {addSpace: true});
if (this._massTagInputNode) {
- new TagAutoCompleteControl(
+ this._masstagAutoCompleteControl = new TagAutoCompleteControl(
this._massTagInputNode, {addSpace: false});
}
- keyboard.bind('q', () => {
- this._formNode.querySelector('input:first-of-type').focus();
- });
-
- keyboard.bind('p', () => {
- const firstPostNode =
- document.body.querySelector('.post-list li:first-child a');
- if (firstPostNode) {
- firstPostNode.focus();
- }
- });
+ keyboard.bind('p', () => this._focusFirstPostNode());
+ search.searchInputNodeFocusHelper(this._queryInputNode);
for (let safetyButtonNode of this._safetyButtonNodes) {
safetyButtonNode.addEventListener(
@@ -51,8 +44,6 @@ class PostsHeaderView {
}
this._stopMassTagLinkNode.addEventListener(
'click', e => this._evtStopTaggingClick(e));
- // this._massTagFormNode.addEventListener(
- // 'submit', e => this._evtMassTagFormSubmit(e));
this._toggleMassTagVisibility(!!ctx.parameters.tag);
}
}
@@ -93,10 +84,11 @@ class PostsHeaderView {
_evtStopTaggingClick(e) {
e.preventDefault();
- router.show('/posts/' + misc.formatUrlParameters({
+ this._toggleMassTagVisibility(false);
+ this.dispatchEvent(new CustomEvent('navigate', {detail: {parameters: {
query: this._ctx.parameters.query,
page: this._ctx.parameters.page,
- }));
+ }}}));
}
_evtSafetyButtonClick(e, url) {
@@ -107,20 +99,35 @@ class PostsHeaderView {
browsingSettings.listPosts[safety] =
!browsingSettings.listPosts[safety];
settings.save(browsingSettings, true);
- router.show(router.url);
+ this.dispatchEvent(
+ new CustomEvent(
+ 'navigate', {detail: {parameters: this._ctx.parameters}}));
}
_evtFormSubmit(e) {
e.preventDefault();
- let params = {
+ this._queryAutoCompleteControl.hide();
+ if (this._masstagAutoCompleteControl) {
+ this._masstagAutoCompleteControl.hide();
+ }
+ let parameters = {
query: this._queryInputNode.value,
page: this._ctx.parameters.page,
};
if (this._massTagInputNode) {
- params.tag = this._massTagInputNode.value;
+ parameters.tag = this._massTagInputNode.value;
this._massTagInputNode.blur();
}
- router.show('/posts/' + misc.formatUrlParameters(params));
+ this.dispatchEvent(
+ new CustomEvent('navigate', {detail: {parameters: parameters}}));
+ }
+
+ _focusFirstPostNode() {
+ const firstPostNode =
+ document.body.querySelector('.post-list li:first-child a');
+ if (firstPostNode) {
+ firstPostNode.focus();
+ }
}
}
diff --git a/client/js/views/tags_header_view.js b/client/js/views/tags_header_view.js
index a9babc2..a395d4f 100644
--- a/client/js/views/tags_header_view.js
+++ b/client/js/views/tags_header_view.js
@@ -1,16 +1,18 @@
'use strict';
-const router = require('../router.js');
-const keyboard = require('../util/keyboard.js');
+const events = require('../events.js');
const misc = require('../util/misc.js');
+const search = require('../util/search.js');
const views = require('../util/views.js');
const TagAutoCompleteControl =
require('../controls/tag_auto_complete_control.js');
const template = views.getTemplate('tags-header');
-class TagsHeaderView {
+class TagsHeaderView extends events.EventTarget {
constructor(ctx) {
+ super();
+
this._hostNode = ctx.hostNode;
views.replaceContent(this._hostNode, template(ctx));
@@ -18,9 +20,7 @@ class TagsHeaderView {
new TagAutoCompleteControl(this._queryInputNode);
}
- keyboard.bind('q', () => {
- form.querySelector('input').focus();
- });
+ search.searchInputNodeFocusHelper(this._queryInputNode);
this._formNode.addEventListener('submit', e => this._evtSubmit(e));
}
@@ -36,10 +36,9 @@ class TagsHeaderView {
_evtSubmit(e) {
e.preventDefault();
this._queryInputNode.blur();
- router.show(
- '/tags/' + misc.formatUrlParameters({
- query: this._queryInputNode.value,
- }));
+ this.dispatchEvent(new CustomEvent('navigate', {detail: {parameters: {
+ query: this._queryInputNode.value,
+ }}}));
}
}
diff --git a/client/js/views/users_header_view.js b/client/js/views/users_header_view.js
index 8678025..21ba1f1 100644
--- a/client/js/views/users_header_view.js
+++ b/client/js/views/users_header_view.js
@@ -1,20 +1,20 @@
'use strict';
-const router = require('../router.js');
-const keyboard = require('../util/keyboard.js');
+const events = require('../events.js');
const misc = require('../util/misc.js');
+const search = require('../util/search.js');
const views = require('../util/views.js');
const template = views.getTemplate('users-header');
-class UsersHeaderView {
+class UsersHeaderView extends events.EventTarget {
constructor(ctx) {
+ super();
+
this._hostNode = ctx.hostNode;
views.replaceContent(this._hostNode, template(ctx));
- keyboard.bind('q', () => {
- this._formNode.querySelector('input').focus();
- });
+ search.searchInputNodeFocusHelper(this._queryInputNode);
this._formNode.addEventListener('submit', e => this._evtSubmit(e));
}
@@ -29,11 +29,9 @@ class UsersHeaderView {
_evtSubmit(e) {
e.preventDefault();
- this._queryInputNode.blur();
- router.show(
- '/users/' + misc.formatUrlParameters({
- query: this._queryInputNode.value,
- }));
+ this.dispatchEvent(new CustomEvent('navigate', {detail: {parameters: {
+ query: this._queryInputNode.value,
+ }}}));
}
}