[#124,refactor,view][s]: ([m] in effect) rename DataExplorer view to MultiView and split contents view.js into separate files - fixes #124.

This commit is contained in:
Rufus Pollock
2012-05-31 21:36:52 +01:00
parent c1c1881660
commit 53327a7a1e
10 changed files with 275 additions and 25 deletions

View File

@@ -70,7 +70,7 @@
//
// State is available not only for individual views (as described above) but
// for the dataset (e.g. the current query). For an example of pulling together
// state from across multiple components see `recline.View.DataExplorer`.
// state from across multiple components see `recline.View.MultiView`.
//
// ### Flash Messages / Notifications
//
@@ -85,7 +85,7 @@
//
// Objects or views wishing to bind to flash messages may then subscribe to
// these events and take some action such as displaying them to the user. For
// an example of such behaviour see the DataExplorer view.
// an example of such behaviour see the MultiView view.
//
// ### Writing your own Views
//
@@ -98,12 +98,12 @@ this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
// ## DataExplorer
// ## MultiView
//
// The primary view for the entire application. Usage:
// Manage multiple views together along with query editor etc. Usage:
//
// <pre>
// var myExplorer = new model.recline.DataExplorer({
// var myExplorer = new model.recline.MultiView({
// model: {{recline.Model.Dataset instance}}
// el: {{an existing dom element}}
// views: {{dataset views}}
@@ -120,7 +120,7 @@ this.recline.View = this.recline.View || {};
// Graph).
//
// **views**: (optional) the dataset views (Grid, Graph etc) for
// DataExplorer to show. This is an array of view hashes. If not provided
// MultiView to show. This is an array of view hashes. If not provided
// initialize with (recline.View.)Grid, Graph, and Map views (with obvious id
// and labels!).
//
@@ -161,8 +161,8 @@ this.recline.View = this.recline.View || {};
// Note that at present we do *not* serialize information about the actual set
// of views in use -- e.g. those specified by the views argument -- but instead
// expect either that the default views are fine or that the client to have
// initialized the DataExplorer with the relevant views themselves.
my.DataExplorer = Backbone.View.extend({
// initialized the MultiView with the relevant views themselves.
my.MultiView = Backbone.View.extend({
template: ' \
<div class="recline-data-explorer"> \
<div class="alert-messages"></div> \
@@ -453,12 +453,12 @@ my.DataExplorer = Backbone.View.extend({
}
});
// ### DataExplorer.restore
// ### MultiView.restore
//
// Restore a DataExplorer instance from a serialized state including the associated dataset
my.DataExplorer.restore = function(state) {
// Restore a MultiView instance from a serialized state including the associated dataset
my.MultiView.restore = function(state) {
var dataset = recline.Model.Dataset.restore(state);
var explorer = new my.DataExplorer({
var explorer = new my.MultiView({
model: dataset,
state: state
});

80
src/widget.facetviewer.js Normal file
View File

@@ -0,0 +1,80 @@
/*jshint multistr:true */
this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
my.FacetViewer = Backbone.View.extend({
className: 'recline-facet-viewer well',
template: ' \
<a class="close js-hide" href="#">&times;</a> \
<div class="facets row"> \
<div class="span1"> \
<h3>Facets</h3> \
</div> \
{{#facets}} \
<div class="facet-summary span2 dropdown" data-facet="{{id}}"> \
<a class="btn dropdown-toggle" data-toggle="dropdown" href="#"><i class="icon-chevron-down"></i> {{id}} {{label}}</a> \
<ul class="facet-items dropdown-menu"> \
{{#terms}} \
<li><a class="facet-choice js-facet-filter" data-value="{{term}}">{{term}} ({{count}})</a></li> \
{{/terms}} \
{{#entries}} \
<li><a class="facet-choice js-facet-filter" data-value="{{time}}">{{term}} ({{count}})</a></li> \
{{/entries}} \
</ul> \
</div> \
{{/facets}} \
</div> \
',
events: {
'click .js-hide': 'onHide',
'click .js-facet-filter': 'onFacetFilter'
},
initialize: function(model) {
_.bindAll(this, 'render');
this.el = $(this.el);
this.model.facets.bind('all', this.render);
this.model.fields.bind('all', this.render);
this.render();
},
render: function() {
var tmplData = {
facets: this.model.facets.toJSON(),
fields: this.model.fields.toJSON()
};
tmplData.facets = _.map(tmplData.facets, function(facet) {
if (facet._type === 'date_histogram') {
facet.entries = _.map(facet.entries, function(entry) {
entry.term = new Date(entry.time).toDateString();
return entry;
});
}
return facet;
});
var templated = Mustache.render(this.template, tmplData);
this.el.html(templated);
// are there actually any facets to show?
if (this.model.facets.length > 0) {
this.el.show();
} else {
this.el.hide();
}
},
onHide: function(e) {
e.preventDefault();
this.el.hide();
},
onFacetFilter: function(e) {
var $target= $(e.target);
var fieldId = $target.closest('.facet-summary').attr('data-facet');
var value = $target.attr('data-value');
this.model.queryState.addTermFilter(fieldId, value);
}
});
})(jQuery, recline.View);

65
src/widget.queryeditor.js Normal file
View File

@@ -0,0 +1,65 @@
/*jshint multistr:true */
this.recline = this.recline || {};
this.recline.View = this.recline.View || {};
(function($, my) {
my.QueryEditor = Backbone.View.extend({
className: 'recline-query-editor',
template: ' \
<form action="" method="GET" class="form-inline"> \
<div class="input-prepend text-query"> \
<span class="add-on"><i class="icon-search"></i></span> \
<input type="text" name="q" value="{{q}}" class="span2" placeholder="Search data ..." class="search-query" /> \
</div> \
<div class="pagination"> \
<ul> \
<li class="prev action-pagination-update"><a href="">&laquo;</a></li> \
<li class="active"><a><input name="from" type="text" value="{{from}}" /> &ndash; <input name="to" type="text" value="{{to}}" /> </a></li> \
<li class="next action-pagination-update"><a href="">&raquo;</a></li> \
</ul> \
</div> \
<button type="submit" class="btn">Go &raquo;</button> \
</form> \
',
events: {
'submit form': 'onFormSubmit',
'click .action-pagination-update': 'onPaginationUpdate'
},
initialize: function() {
_.bindAll(this, 'render');
this.el = $(this.el);
this.model.bind('change', this.render);
this.render();
},
onFormSubmit: function(e) {
e.preventDefault();
var query = this.el.find('.text-query input').val();
var newFrom = parseInt(this.el.find('input[name="from"]').val());
var newSize = parseInt(this.el.find('input[name="to"]').val()) - newFrom;
this.model.set({size: newSize, from: newFrom, q: query});
},
onPaginationUpdate: function(e) {
e.preventDefault();
var $el = $(e.target);
var newFrom = 0;
if ($el.parent().hasClass('prev')) {
newFrom = this.model.get('from') - Math.max(0, this.model.get('size'));
} else {
newFrom = this.model.get('from') + this.model.get('size');
}
this.model.set({from: newFrom});
},
render: function() {
var tmplData = this.model.toJSON();
tmplData.to = this.model.get('from') + this.model.get('size');
var templated = Mustache.render(this.template, tmplData);
this.el.html(templated);
}
});
})(jQuery, recline.View);