[#147,widget/filtereditor][m]: add filter support in filter widget plus move to sidebar and tidy up.

* model.js: xsmall tweak to set value of term filter to empty string rather than null.
This commit is contained in:
Rufus Pollock
2012-06-06 23:59:09 +01:00
parent 68b6a9356f
commit 26350fec06
6 changed files with 100 additions and 39 deletions

View File

@@ -96,14 +96,21 @@
* Filter Editor * Filter Editor
*********************************************************/ *********************************************************/
.recline-filter-editor .filter-term .input-append a { .recline-filter-editor {
margin-left: -5px; padding: 8px;
} }
.recline-facet-viewer .facet-summary label { .recline-filter-editor .filter-term a {
display: inline; font-size: 18px;
} }
.recline-filter-editor input,
.recline-filter-editor select
{
width: 175px;
}
/********************************************************** /**********************************************************
* Fields Widget * Fields Widget
*********************************************************/ *********************************************************/

View File

@@ -425,7 +425,7 @@ my.Query = Backbone.Model.extend({
addTermFilter: function(fieldId, value) { addTermFilter: function(fieldId, value) {
var filters = this.get('filters'); var filters = this.get('filters');
var filter = { term: {} }; var filter = { term: {} };
filter.term[fieldId] = value; filter.term[fieldId] = value || '';
filters.push(filter); filters.push(filter);
this.set({filters: filters}); this.set({filters: filters});
// change does not seem to be triggered automatically // change does not seem to be triggered automatically

View File

@@ -224,10 +224,16 @@ my.MultiView = Backbone.View.extend({
this.el.find('.query-editor-here').append(queryEditor.el); this.el.find('.query-editor-here').append(queryEditor.el);
var filterEditor = new recline.View.FilterEditor({ var filterEditor = new recline.View.FilterEditor({
model: this.model.queryState model: this.model
}); });
this.$filterEditor = filterEditor.el; this.$filterEditor = filterEditor.el;
this.el.find('.header').append(filterEditor.el); $dataSidebar.append(filterEditor.el);
// are there actually any filters to show?
if (this.model.get('filters') && this.model.get('filters').length > 0) {
this.$filterEditor.show();
} else {
this.$filterEditor.hide();
}
var fieldsView = new recline.View.Fields({ var fieldsView = new recline.View.Fields({
model: this.model model: this.model

View File

@@ -8,37 +8,45 @@ this.recline.View = this.recline.View || {};
my.FilterEditor = Backbone.View.extend({ my.FilterEditor = Backbone.View.extend({
className: 'recline-filter-editor well', className: 'recline-filter-editor well',
template: ' \ template: ' \
<div class="row filters"> \ <div class="filters"> \
<div class="span1"> \ <h3>Filters</h3> \
<h3>Filters</h3> \ <a href="#" class="js-add-filter">Add filter</a> \
</div> \ <form class="form-stacked js-add" style="display: none;"> \
<div class="span11"> \ <fieldset> \
<form class="form-horizontal"> \ <label>Filter type</label> \
<div class="row"> \ <select class="filterType"> \
<div class="span6"> \ <option value="term">Term (text) filter</option> \
{{#termFilters}} \ </select> \
<div class="control-group filter-term filter" data-filter-id={{id}}> \ <label>Field</label> \
<label class="control-label" for="">{{label}}</label> \ <select class="fields"> \
<div class="controls"> \ {{#fields}} \
<div class="input-append"> \ <option value="{{id}}">{{label}}</option> \
<input type="text" value="{{value}}" name="{{fieldId}}" class="span4" data-filter-field="{{fieldId}}" data-filter-id="{{id}}" data-filter-type="term" /> \ {{/fields}} \
<a class="btn js-remove-filter"><i class="icon-remove"></i></a> \ </select> \
</div> \ <button type="submit" class="btn">Add</button> \
</div> \ </fieldset> \
</div> \ </form> \
{{/termFilters}} \ <form class="form-stacked js-edit"> \
</div> \ {{#termFilters}} \
<div class="span4"> \ <div class="control-group filter-term filter" data-filter-id={{id}}> \
<p>To add a filter use the column menu in the grid view.</p> \ <label class="control-label" for="">{{label}}</label> \
<button type="submit" class="btn">Update</button> \ <div class="controls"> \
<input type="text" value="{{value}}" name="{{fieldId}}" data-filter-field="{{fieldId}}" data-filter-id="{{id}}" data-filter-type="term" /> \
<a class="js-remove-filter" href="#">&times;</a> \
</div> \ </div> \
</form> \ </div> \
</div> \ {{/termFilters}} \
{{#termFilters.length}} \
<button type="submit" class="btn">Update</button> \
{{/termFilters.length}} \
</form> \
</div> \ </div> \
', ',
events: { events: {
'click .js-remove-filter': 'onRemoveFilter', 'click .js-remove-filter': 'onRemoveFilter',
'submit form': 'onTermFiltersUpdate' 'click .js-add-filter': 'onAddFilterShow',
'submit form.js-edit': 'onTermFiltersUpdate',
'submit form.js-add': 'onAddFilter'
}, },
initialize: function() { initialize: function() {
this.el = $(this.el); this.el = $(this.el);
@@ -48,7 +56,7 @@ my.FilterEditor = Backbone.View.extend({
this.render(); this.render();
}, },
render: function() { render: function() {
var tmplData = $.extend(true, {}, this.model.toJSON()); var tmplData = $.extend(true, {}, this.model.queryState.toJSON());
// we will use idx in list as there id ... // we will use idx in list as there id ...
tmplData.filters = _.map(tmplData.filters, function(filter, idx) { tmplData.filters = _.map(tmplData.filters, function(filter, idx) {
filter.id = idx; filter.id = idx;
@@ -66,14 +74,27 @@ my.FilterEditor = Backbone.View.extend({
value: filter.term[fieldId] value: filter.term[fieldId]
}; };
}); });
tmplData.fields = this.model.fields.toJSON();
var out = Mustache.render(this.template, tmplData); var out = Mustache.render(this.template, tmplData);
this.el.html(out); this.el.html(out);
// are there actually any facets to show? },
if (this.model.get('filters').length > 0) { onAddFilterShow: function(e) {
this.el.show(); e.preventDefault();
} else { var $target = $(e.target);
this.el.hide(); $target.hide();
this.el.find('form.js-add').show();
},
onAddFilter: function(e) {
e.preventDefault();
var $target = $(e.target);
$target.hide();
var filterType = $target.find('select.filterType').val();
var field = $target.find('select.fields').val();
if (filterType === 'term') {
this.model.queryState.addTermFilter(field);
} }
// trigger render explicitly as queryState change will not be triggered (as blank value for filter)
this.render();
}, },
onRemoveFilter: function(e) { onRemoveFilter: function(e) {
e.preventDefault(); e.preventDefault();

View File

@@ -62,6 +62,7 @@
<script type="text/javascript" src="view.timeline.test.js"></script> <script type="text/javascript" src="view.timeline.test.js"></script>
<script type="text/javascript" src="view.multiview.test.js"></script> <script type="text/javascript" src="view.multiview.test.js"></script>
<script type="text/javascript" src="util.test.js"></script> <script type="text/javascript" src="util.test.js"></script>
<script type="text/javascript" src="widget.filtereditor.test.js"></script>
</head> </head>
<body> <body>
<h1 id="qunit-header">Qunit Tests</h1> <h1 id="qunit-header">Qunit Tests</h1>

View File

@@ -0,0 +1,26 @@
module("Widget - Filter Editor");
test('basics', function () {
var dataset = Fixture.getDataset();
var view = new recline.View.FilterEditor({
model: dataset
});
$('.fixtures').append(view.el);
assertPresent('.js-add-filter', view.elSidebar);
var $addForm = view.el.find('form.js-add');
ok(!$addForm.is(":visible"));
view.el.find('.js-add-filter').click();
ok(!view.el.find('.js-add-filter').is(":visible"));
ok($addForm.is(":visible"));
$addForm.find('select.fields').val('country');
$addForm.submit();
ok(!$addForm.is(":visible"));
$editForm = view.el.find('form.js-edit');
equal($editForm.find('.filter-term').length, 1)
equal(_.keys(dataset.queryState.attributes.filters[0].term)[0], 'country');
view.remove();
});