modify pager widget to handle boundary conditions; now takes a Dataset instead of a Query so that it has access to the record count; add tests
This commit is contained in:
@@ -143,7 +143,7 @@ var SearchView = Backbone.View.extend({
|
|||||||
this.el.find('.sidebar').append(view.el);
|
this.el.find('.sidebar').append(view.el);
|
||||||
|
|
||||||
var pager = new recline.View.Pager({
|
var pager = new recline.View.Pager({
|
||||||
model: this.model.queryState
|
model: this.model
|
||||||
});
|
});
|
||||||
this.el.find('.pager-here').append(pager.el);
|
this.el.find('.pager-here').append(pager.el);
|
||||||
|
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ my.MultiView = Backbone.View.extend({
|
|||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
this.pager = new recline.View.Pager({
|
this.pager = new recline.View.Pager({
|
||||||
model: this.model.queryState
|
model: this.model
|
||||||
});
|
});
|
||||||
this.$el.find('.recline-results-info').after(this.pager.el);
|
this.$el.find('.recline-results-info').after(this.pager.el);
|
||||||
|
|
||||||
|
|||||||
@@ -25,34 +25,43 @@ my.Pager = Backbone.View.extend({
|
|||||||
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
_.bindAll(this, 'render');
|
_.bindAll(this, 'render');
|
||||||
this.listenTo(this.model, 'change', this.render);
|
this.listenTo(this.model.queryState, 'change', this.render);
|
||||||
this.render();
|
this.render();
|
||||||
},
|
},
|
||||||
onFormSubmit: function(e) {
|
onFormSubmit: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var newFrom = parseInt(this.$el.find('input[name="from"]').val());
|
var newFrom = parseInt(this.$el.find('input[name="from"]').val());
|
||||||
|
newFrom = Math.min(this.model.recordCount, Math.max(newFrom, 1))-1;
|
||||||
var newSize = parseInt(this.$el.find('input[name="to"]').val()) - newFrom;
|
var newSize = parseInt(this.$el.find('input[name="to"]').val()) - newFrom;
|
||||||
newFrom = Math.max(newFrom, 0);
|
newSize = Math.min(Math.max(newSize, 1), this.model.recordCount);
|
||||||
newSize = Math.max(newSize, 1);
|
this.model.queryState.set({size: newSize, from: newFrom});
|
||||||
this.model.set({size: newSize, from: newFrom});
|
|
||||||
},
|
},
|
||||||
onPaginationUpdate: function(e) {
|
onPaginationUpdate: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var $el = $(e.target);
|
var $el = $(e.target);
|
||||||
var newFrom = 0;
|
var newFrom = 0;
|
||||||
|
var currFrom = this.model.queryState.get('from');
|
||||||
|
var size = this.model.queryState.get('size');
|
||||||
|
var updateQuery = false;
|
||||||
if ($el.parent().hasClass('prev')) {
|
if ($el.parent().hasClass('prev')) {
|
||||||
newFrom = this.model.get('from') - Math.max(0, this.model.get('size'));
|
newFrom = Math.max(currFrom - Math.max(0, size), 1)-1;
|
||||||
|
updateQuery = newFrom != currFrom;
|
||||||
} else {
|
} else {
|
||||||
newFrom = this.model.get('from') + this.model.get('size');
|
newFrom = Math.max(currFrom + size, 1);
|
||||||
|
updateQuery = (newFrom < this.model.recordCount);
|
||||||
|
}
|
||||||
|
if (updateQuery) {
|
||||||
|
this.model.queryState.set({from: newFrom});
|
||||||
}
|
}
|
||||||
newFrom = Math.max(newFrom, 0);
|
|
||||||
this.model.set({from: newFrom});
|
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var tmplData = this.model.toJSON();
|
var tmplData = this.model.toJSON();
|
||||||
tmplData.to = this.model.get('from') + this.model.get('size');
|
var from = parseInt(this.model.queryState.get('from'));
|
||||||
|
tmplData.from = from+1;
|
||||||
|
tmplData.to = Math.min(from+this.model.queryState.get('size'), this.model.recordCount);
|
||||||
var templated = Mustache.render(this.template, tmplData);
|
var templated = Mustache.render(this.template, tmplData);
|
||||||
this.$el.html(templated);
|
this.$el.html(templated);
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,7 @@
|
|||||||
<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>
|
<script type="text/javascript" src="widget.filtereditor.test.js"></script>
|
||||||
<script type="text/javascript" src="widget.valuefilter.test.js"></script>
|
<script type="text/javascript" src="widget.valuefilter.test.js"></script>
|
||||||
|
<script type="text/javascript" src="widget.pager.test.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1 id="qunit-header">Qunit Tests</h1>
|
<h1 id="qunit-header">Qunit Tests</h1>
|
||||||
|
|||||||
99
test/widget.pager.test.js
Normal file
99
test/widget.pager.test.js
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
module("Widget - Pager");
|
||||||
|
|
||||||
|
test('basics', function () {
|
||||||
|
var dataset = Fixture.getDataset();
|
||||||
|
var size = dataset.recordCount/2 + 1;
|
||||||
|
dataset.queryState.set({ size : size }, { silent : true });
|
||||||
|
var view = new recline.View.Pager({
|
||||||
|
model: dataset
|
||||||
|
});
|
||||||
|
$('.fixtures').append(view.el);
|
||||||
|
var fromSelector = 'input[name=from]';
|
||||||
|
var toSelector = 'input[name=to]';
|
||||||
|
|
||||||
|
assertPresent('.pagination', view.elSidebar);
|
||||||
|
// next and prev present
|
||||||
|
assertPresent('.prev', view.elSidebar);
|
||||||
|
assertPresent('.next', view.elSidebar);
|
||||||
|
|
||||||
|
// from and to inputs present
|
||||||
|
assertPresent(fromSelector, view.elSidebar);
|
||||||
|
assertPresent(toSelector, view.elSidebar);
|
||||||
|
|
||||||
|
// click next: -> reload from+size - recordCount
|
||||||
|
var prevFromVal = parseInt($(fromSelector).val());
|
||||||
|
var prevToVal = parseInt($(toSelector).val());
|
||||||
|
view.$el.find('.next a').click();
|
||||||
|
equal($(fromSelector).val(), prevFromVal+size);
|
||||||
|
// to = recordCount since size is more than half of record count
|
||||||
|
equal($(toSelector).val(), dataset.recordCount);
|
||||||
|
// UI is 1-based but model is zero-based
|
||||||
|
equal(dataset.queryState.get('from'), prevFromVal+size-1);
|
||||||
|
|
||||||
|
// click prev -> 1-4, model from=0
|
||||||
|
prevFromVal = parseInt($(fromSelector).val());
|
||||||
|
prevToVal = parseInt($(toSelector).val());
|
||||||
|
view.$el.find('.prev a').click();
|
||||||
|
equal($(fromSelector).val(), prevFromVal-size);
|
||||||
|
equal($(toSelector).val(), prevFromVal-1);
|
||||||
|
// UI is 1-based but model is zero-based
|
||||||
|
equal(dataset.queryState.get('from'), prevFromVal-size-1);
|
||||||
|
|
||||||
|
view.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('bounds checking', function () {
|
||||||
|
var dataset = Fixture.getDataset();
|
||||||
|
var size = dataset.recordCount/2 + 1;
|
||||||
|
dataset.queryState.set({ size : size }, { silent : true });
|
||||||
|
var view = new recline.View.Pager({
|
||||||
|
model: dataset
|
||||||
|
});
|
||||||
|
$('.fixtures').append(view.el);
|
||||||
|
var querySpy = sinon.spy(dataset, 'query');
|
||||||
|
var fromSelector = 'input[name=from]';
|
||||||
|
var toSelector = 'input[name=to]';
|
||||||
|
|
||||||
|
// click prev on beginning: nothing happens
|
||||||
|
view.$el.find('.prev a').click();
|
||||||
|
equal($(fromSelector).val(), 1);
|
||||||
|
equal($(toSelector).val(), size);
|
||||||
|
ok(!dataset.query.called);
|
||||||
|
|
||||||
|
// enter size-1 in from: reloads size-1 - size
|
||||||
|
var fromVal = size-1;
|
||||||
|
var toVal = parseInt($(toSelector).val());
|
||||||
|
$(fromSelector).val(fromVal).change();
|
||||||
|
equal($(fromSelector).val(), fromVal);
|
||||||
|
equal($(toSelector).val(), toVal);
|
||||||
|
// UI is 1-based but model is zero-based
|
||||||
|
equal(dataset.queryState.get('from'), fromVal-1);
|
||||||
|
|
||||||
|
// enter value past the end in from: reloads recordCount - recordCount
|
||||||
|
fromVal = dataset.recordCount + 10;
|
||||||
|
$(fromSelector).val(fromVal).change();
|
||||||
|
equal($(fromSelector).val(), dataset.recordCount);
|
||||||
|
equal($(toSelector).val(), dataset.recordCount);
|
||||||
|
// UI is 1-based but model is zero-based
|
||||||
|
equal(dataset.queryState.get('from'), dataset.recordCount-1);
|
||||||
|
|
||||||
|
// click next on end -> nothing happens
|
||||||
|
var queryCalls = querySpy.callCount;
|
||||||
|
fromVal = parseInt($(fromSelector).val());
|
||||||
|
toVal = parseInt($(toSelector).val());
|
||||||
|
view.$el.find('.next a').click();
|
||||||
|
equal(querySpy.callCount, queryCalls);
|
||||||
|
equal($(fromSelector).val(), fromVal);
|
||||||
|
equal($(toSelector).val(), toVal);
|
||||||
|
|
||||||
|
// reset from to 1
|
||||||
|
// type value past the end in to: 1-recordCount
|
||||||
|
fromVal = 1;
|
||||||
|
toVal = dataset.recordCount + 10;
|
||||||
|
$(fromSelector).val(fromVal);
|
||||||
|
$(toSelector).val(toVal).change();
|
||||||
|
equal($(fromSelector).val(), 1);
|
||||||
|
equal($(toSelector).val(), dataset.recordCount);
|
||||||
|
|
||||||
|
view.remove();
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user