[#62,faceting][s]: introduce Facet and FacetList models and use them.
* Conceptual breakthrough on how Faceting and Filtering interact (have updated issue #62 as a result).
This commit is contained in:
@@ -95,9 +95,10 @@ function localDataset() {
|
|||||||
backend.addDataset(inData);
|
backend.addDataset(inData);
|
||||||
var dataset = new recline.Model.Dataset({id: datasetId}, backend);
|
var dataset = new recline.Model.Dataset({id: datasetId}, backend);
|
||||||
// TODO: auto-compute in Memory backend ??
|
// TODO: auto-compute in Memory backend ??
|
||||||
dataset.facets = {
|
dataset.facets = new recline.Model.FacetList([
|
||||||
'country': {
|
{
|
||||||
terms: [
|
id: 'country',
|
||||||
|
result: [
|
||||||
{
|
{
|
||||||
term: 'UK',
|
term: 'UK',
|
||||||
count: 3
|
count: 3
|
||||||
@@ -112,7 +113,7 @@ function localDataset() {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
]);
|
||||||
return dataset;
|
return dataset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
34
src/model.js
34
src/model.js
@@ -23,7 +23,7 @@ my.Dataset = Backbone.Model.extend({
|
|||||||
}
|
}
|
||||||
this.fields = new my.FieldList();
|
this.fields = new my.FieldList();
|
||||||
this.currentDocuments = new my.DocumentList();
|
this.currentDocuments = new my.DocumentList();
|
||||||
this.facets = {};
|
this.facets = new my.FacetList();
|
||||||
this.docCount = null;
|
this.docCount = null;
|
||||||
this.queryState = new my.Query();
|
this.queryState = new my.Query();
|
||||||
this.queryState.bind('change', this.query);
|
this.queryState.bind('change', this.query);
|
||||||
@@ -119,24 +119,36 @@ my.Query = Backbone.Model.extend({
|
|||||||
, from: 0
|
, from: 0
|
||||||
, facets: {}
|
, facets: {}
|
||||||
},
|
},
|
||||||
initialize: function() {
|
// Set (update or add) a terms filter
|
||||||
_.bindAll(this, 'addFacet');
|
// http://www.elasticsearch.org/guide/reference/query-dsl/terms-filter.html
|
||||||
},
|
setFilter: function(fieldId, values) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
my.Facet = Backbone.Model.extend({
|
||||||
|
defaults: {
|
||||||
|
query: null,
|
||||||
|
result: null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
my.FacetList = Backbone.Collection.extend({
|
||||||
|
model: my.Facet,
|
||||||
addFacet: function(fieldId) {
|
addFacet: function(fieldId) {
|
||||||
// TODO: utilize field info to determine facet type ??
|
// Assume id and fieldId should be the same (TODO: this need not be true if we want to add two different type of facets on same field)
|
||||||
var facets = this.get('facets');
|
if (fieldId in this) {
|
||||||
if (fieldId in facets) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
facets[fieldId] = {
|
// TODO: utilize field info to determine facet type ??
|
||||||
|
var facet = new my.Facet({
|
||||||
|
id: fieldId,
|
||||||
|
query: {
|
||||||
terms: {
|
terms: {
|
||||||
field: fieldId
|
field: fieldId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.set({facets: facets});
|
});
|
||||||
// trigger change event (does not seem to be triggered o/w)
|
this.add(facet);
|
||||||
// this.change();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
54
src/view.js
54
src/view.js
@@ -168,11 +168,9 @@ my.DataExplorer = Backbone.View.extend({
|
|||||||
model: this.model.queryState
|
model: this.model.queryState
|
||||||
});
|
});
|
||||||
this.el.find('.header').append(queryEditor.el);
|
this.el.find('.header').append(queryEditor.el);
|
||||||
var queryFacetEditor = new my.QueryFacetEditor({
|
var queryFacetEditor = new my.FacetQueryEditor({
|
||||||
model: this.model.queryState
|
model: this.model
|
||||||
},
|
});
|
||||||
this.model
|
|
||||||
);
|
|
||||||
this.el.find('.header').append(queryFacetEditor.el);
|
this.el.find('.header').append(queryFacetEditor.el);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -281,58 +279,52 @@ my.QueryEditor = Backbone.View.extend({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
my.QueryFacetEditor = Backbone.View.extend({
|
my.FacetQueryEditor = Backbone.View.extend({
|
||||||
className: 'recline-query-facet-editor',
|
className: 'recline-query-facet-editor',
|
||||||
template: ' \
|
template: ' \
|
||||||
<a class="btn dropdown-toggle" data-toggle="drop-down">Add filter on</a> \
|
<div class="dropdown js-add-facet"> \
|
||||||
<ul class="dropdown-menu js-faceton"> \
|
<a class="btn dropdown-toggle" data-toggle="dropdown" href=".js-add-facet">Add Facet On <i class="caret"></i></a> \
|
||||||
|
<ul class="dropdown-menu"> \
|
||||||
{{#fields}} \
|
{{#fields}} \
|
||||||
<li name="{{id}}">{{label}}</li> \
|
<li><a href="#{{id}}">{{label}}</a></li> \
|
||||||
{{/fields}} \
|
{{/fields}} \
|
||||||
</ul> \
|
</ul> \
|
||||||
|
</div> \
|
||||||
<div class="facets"> \
|
<div class="facets"> \
|
||||||
{{#facets}} \
|
{{#facets}} \
|
||||||
<a class="btn js-facet-show-toggle" data-facet="{{label}}"><i class="icon-plus"></i> {{label}}</a> \
|
<a class="btn js-facet-show-toggle" data-facet="{{id}}"><i class="icon-plus"></i> {{id}} {{label}}</a> \
|
||||||
<ul class="facet-items" data-facet="{{label}}" style="display: none;"> \
|
<ul class="facet-items" data-facet="{{id}}" style="display: none;"> \
|
||||||
{{#terms}} \
|
{{#result}} \
|
||||||
<li>{{term}} ({{count}}) <input type="checkbox" class="facet-choice" data-facet="{{label}}" value="{{term}}" /></li> \
|
<li>{{term}} ({{count}}) <input type="checkbox" class="facet-choice" data-facet="{{label}}" value="{{term}}" /></li> \
|
||||||
{{/terms}} \
|
{{/result}} \
|
||||||
</ul> \
|
</ul> \
|
||||||
{{/facets}} \
|
{{/facets}} \
|
||||||
</div> \
|
</div> \
|
||||||
',
|
',
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
'change .js-faceton': 'onAddFilter',
|
'click .js-add-facet .dropdown-menu a': 'onAddFacet',
|
||||||
'click .js-facet-show-toggle': 'onFacetShowToggle'
|
'click .js-facet-show-toggle': 'onFacetShowToggle'
|
||||||
},
|
},
|
||||||
initialize: function(model, dataset) {
|
initialize: function(model) {
|
||||||
_.bindAll(this, 'render');
|
_.bindAll(this, 'render');
|
||||||
this.el = $(this.el);
|
this.el = $(this.el);
|
||||||
this.model.bind('change', this.render);
|
this.model.facets.bind('all', this.render);
|
||||||
this.dataset = dataset;
|
this.model.fields.bind('all', this.render);
|
||||||
this.dataset.fields.bind('add', this.render);
|
|
||||||
this.dataset.fields.bind('reset', this.render);
|
|
||||||
this.dataset.fields.bind('remove', this.render);
|
|
||||||
this.render();
|
this.render();
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var tmplData = {
|
var tmplData = {
|
||||||
query: this.model.toJSON(),
|
facets: this.model.facets.toJSON(),
|
||||||
fields: this.dataset.fields.toJSON()
|
fields: this.model.fields.toJSON()
|
||||||
};
|
};
|
||||||
tmplData.facets = _.map(this.dataset.facets, function(data, key) {
|
|
||||||
var out = _.extend({label: key}, data);
|
|
||||||
return out;
|
|
||||||
})
|
|
||||||
var templated = $.mustache(this.template, tmplData);
|
var templated = $.mustache(this.template, tmplData);
|
||||||
this.el.html(templated);
|
this.el.html(templated);
|
||||||
},
|
},
|
||||||
onAddFilter: function(e) {
|
onAddFacet: function(e) {
|
||||||
var fieldId = $(e.target).find('option:selected').attr('name');
|
e.preventDefault();
|
||||||
this.model.addFacet(fieldId);
|
var fieldId = $(e.target).attr('href').slice(1);
|
||||||
// calculate facets for that field (if not already there??)
|
this.model.facets.addFacet(fieldId);
|
||||||
// re-render will happen automatically as dataset will have updated
|
|
||||||
},
|
},
|
||||||
onFacetShowToggle: function(e) {
|
onFacetShowToggle: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
@@ -43,4 +43,11 @@ test('Dataset', function () {
|
|||||||
equal(out.fields.length, 2);
|
equal(out.fields.length, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Facet', function () {
|
||||||
|
var facets = new recline.Model.FacetList();
|
||||||
|
facets.addFacet('xyz');
|
||||||
|
equal(1, facets.length);
|
||||||
|
deepEqual({terms: {field: 'xyz'}}, facets.get('xyz').get('query'));
|
||||||
|
});
|
||||||
|
|
||||||
})(this.jQuery);
|
})(this.jQuery);
|
||||||
|
|||||||
Reference in New Issue
Block a user