diff --git a/demos/search/demo.search.app.js b/demos/search/demo.search.app.js
index 49f5f9b9..9621ffbf 100644
--- a/demos/search/demo.search.app.js
+++ b/demos/search/demo.search.app.js
@@ -143,7 +143,7 @@ var SearchView = Backbone.View.extend({
this.el.find('.sidebar').append(view.el);
var pager = new recline.View.Pager({
- model: this.model.queryState
+ model: this.model
});
this.el.find('.pager-here').append(pager.el);
diff --git a/src/view.multiview.js b/src/view.multiview.js
index ccd35171..918f0e16 100644
--- a/src/view.multiview.js
+++ b/src/view.multiview.js
@@ -260,7 +260,7 @@ my.MultiView = Backbone.View.extend({
}, this);
this.pager = new recline.View.Pager({
- model: this.model.queryState
+ model: this.model
});
this.$el.find('.recline-results-info').after(this.pager.el);
diff --git a/src/widget.pager.js b/src/widget.pager.js
index b2b5d03d..05e79237 100644
--- a/src/widget.pager.js
+++ b/src/widget.pager.js
@@ -25,34 +25,43 @@ my.Pager = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'render');
- this.listenTo(this.model, 'change', this.render);
+ this.listenTo(this.model.queryState, 'change', this.render);
this.render();
},
onFormSubmit: function(e) {
e.preventDefault();
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;
- newFrom = Math.max(newFrom, 0);
- newSize = Math.max(newSize, 1);
- this.model.set({size: newSize, from: newFrom});
+ newSize = Math.min(Math.max(newSize, 1), this.model.recordCount);
+ this.model.queryState.set({size: newSize, from: newFrom});
},
onPaginationUpdate: function(e) {
e.preventDefault();
var $el = $(e.target);
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')) {
- 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 {
- 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() {
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);
this.$el.html(templated);
+ return this;
}
});
diff --git a/test/index.html b/test/index.html
index 1dc22ed8..87698280 100644
--- a/test/index.html
+++ b/test/index.html
@@ -71,6 +71,7 @@
+
diff --git a/test/widget.pager.test.js b/test/widget.pager.test.js
new file mode 100644
index 00000000..4274fede
--- /dev/null
+++ b/test/widget.pager.test.js
@@ -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();
+});