Improved roster filter UX.

Keep the focus in the input after filtering.
Prevent form submission from reloading the page.
This commit is contained in:
JC Brand 2017-02-13 15:05:43 +00:00
parent f73a1d3fc0
commit fddcd1c6cf
5 changed files with 23 additions and 11 deletions

View File

@ -2112,13 +2112,13 @@
display: none; } display: none; }
#conversejs #converse-roster .search-xmpp ul li.chat-info { #conversejs #converse-roster .search-xmpp ul li.chat-info {
padding-left: 10px; } padding-left: 10px; }
#conversejs #converse-roster .roster-filter-group { #conversejs #converse-roster .roster-filter-form {
margin: 0 1em; margin: 0 1em;
width: 100%; width: 100%;
padding-right: 2em; padding-right: 2em;
/* (jQ addClass:) if input has value: */ /* (jQ addClass:) if input has value: */
/* (jQ addClass:) if mouse is over the 'x' input area*/ } /* (jQ addClass:) if mouse is over the 'x' input area*/ }
#conversejs #converse-roster .roster-filter-group .roster-filter { #conversejs #converse-roster .roster-filter-form .roster-filter {
float: left; float: left;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAABNSURBVHjaXI7BDcAwCAMvyQjMyQ6dAbZiKfqoUK34g2zJh1dENIC7M8pMAPYdzAVY3d0ajNz9aypS/b5R6o+ZPdqoKgCq6h80KH3xDgBqNR97p8oAGQAAAABJRU5ErkJggg==) no-repeat right -20px center; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAABNSURBVHjaXI7BDcAwCAMvyQjMyQ6dAbZiKfqoUK34g2zJh1dENIC7M8pMAPYdzAVY3d0ajNz9aypS/b5R6o+ZPdqoKgCq6h80KH3xDgBqNR97p8oAGQAAAABJRU5ErkJggg==) no-repeat right -20px center;
border: 1px solid #999; border: 1px solid #999;
@ -2128,11 +2128,11 @@
padding: 0; padding: 0;
padding-left: 0.4em; padding-left: 0.4em;
width: 53%; } width: 53%; }
#conversejs #converse-roster .roster-filter-group .roster-filter.x { #conversejs #converse-roster .roster-filter-form .roster-filter.x {
background-position: right 3px center; } background-position: right 3px center; }
#conversejs #converse-roster .roster-filter-group .roster-filter.onX { #conversejs #converse-roster .roster-filter-form .roster-filter.onX {
cursor: pointer; } cursor: pointer; }
#conversejs #converse-roster .roster-filter-group .state-type { #conversejs #converse-roster .roster-filter-form .state-type {
float: left; float: left;
border: 1px solid #999; border: 1px solid #999;
font-size: calc(14px - 2px); font-size: calc(14px - 2px);
@ -2141,7 +2141,7 @@
padding: 0; padding: 0;
padding-left: 0.4em; padding-left: 0.4em;
width: 53%; } width: 53%; }
#conversejs #converse-roster .roster-filter-group .filter-type { #conversejs #converse-roster .roster-filter-form .filter-type {
display: table-cell; display: table-cell;
float: right; float: right;
font-size: calc(14px - 2px); font-size: calc(14px - 2px);

View File

@ -8,6 +8,7 @@
object as first parameter. [jcbrand] object as first parameter. [jcbrand]
- Use lodash instead of underscore.js [jcbrand] - Use lodash instead of underscore.js [jcbrand]
- Escape user-generated input to prevent JS-injection attacks. (Thanks to SamWhited) [jcbrand] - Escape user-generated input to prevent JS-injection attacks. (Thanks to SamWhited) [jcbrand]
- Improved roster filter UX. [jcbrand]
- #486 Honor existing mam user configuration [throwaway42] - #486 Honor existing mam user configuration [throwaway42]
- #749 /me will show your contact's name in the sent field [jcbrand] - #749 /me will show your contact's name in the sent field [jcbrand]
- #774 Browser language (fr-fr or fr) is not detected by default [jcbrand] - #774 Browser language (fr-fr or fr) is not detected by default [jcbrand]

View File

@ -26,7 +26,7 @@
} }
} }
.roster-filter-group { .roster-filter-form {
margin: 0 1em; margin: 0 1em;
width: 100%; width: 100%;
padding-right: 1em + 2*$chat-gutter; padding-right: 1em + 2*$chat-gutter;

View File

@ -139,6 +139,7 @@
tagName: 'span', tagName: 'span',
events: { events: {
"keydown .roster-filter": "liveFilter", "keydown .roster-filter": "liveFilter",
"submit form.roster-filter-form": "submitFilter",
"click .onX": "clearFilter", "click .onX": "clearFilter",
"mousemove .x": "toggleX", "mousemove .x": "toggleX",
"change .filter-type": "changeTypeFilter", "change .filter-type": "changeTypeFilter",
@ -146,7 +147,8 @@
}, },
initialize: function () { initialize: function () {
this.model.on('change', this.render, this); this.model.on('change:filter_type', this.render, this);
this.model.on('change:filter_text', this.render, this);
}, },
render: function () { render: function () {
@ -165,9 +167,13 @@
label_offline: __('Offline') label_offline: __('Offline')
}) })
)); ));
this.renderClearButton();
return this.$el;
},
renderClearButton: function () {
var $roster_filter = this.$('.roster-filter'); var $roster_filter = this.$('.roster-filter');
$roster_filter[this.tog($roster_filter.val())]('x'); $roster_filter[this.tog($roster_filter.val())]('x');
return this.$el;
}, },
tog: function (v) { tog: function (v) {
@ -204,13 +210,18 @@
}, },
liveFilter: _.debounce(function (ev) { liveFilter: _.debounce(function (ev) {
if (ev && ev.preventDefault) { ev.preventDefault(); }
this.model.save({ this.model.save({
'filter_type': this.$('.filter-type').val(), 'filter_type': this.$('.filter-type').val(),
'filter_text': this.$('.roster-filter').val() 'filter_text': this.$('.roster-filter').val()
}); });
}, 250), }, 250),
submitFilter: function (ev) {
if (ev && ev.preventDefault) { ev.preventDefault(); }
this.liveFilter();
this.render();
},
isActive: function () { isActive: function () {
/* Returns true if the filter is enabled (i.e. if the user /* Returns true if the filter is enabled (i.e. if the user
* has added values to the filter). * has added values to the filter).

View File

@ -1,4 +1,4 @@
<form class="pure-form roster-filter-group input-button-group"> <form class="pure-form roster-filter-form input-button-group">
<input value="{{filter_text}}" class="roster-filter" <input value="{{filter_text}}" class="roster-filter"
placeholder="{{placeholder}}" placeholder="{{placeholder}}"
{[ if (filter_type === 'state') { ]} style="display: none" {[ } ]} > {[ if (filter_type === 'state') { ]} style="display: none" {[ } ]} >