9e1490ab by Adam Heath

Initial version of files.

1 parent 5a981a88
.*.swp
.tmp/
dist/
node_modules/
src/lib/
.grunt/
_SpecRunner.html
/* global module */
module.exports = function (grunt) {
/* global require */
'use strict';
var config = {};
config.base = 'src';
config.jshint = {
options: {
},
browserOptions: {
},
};
config.jscs = {
options: {
validateIndentation: 4,
reporter: 'console',
maxErrors: -1,
},
};
config.bower = {
directory: 'lib/bower',
};
config.jasmine = {
withCoverage: true,
};
var montyPython = require('grunt-monty-python')(grunt);
montyPython.createConfig(config);
};
{
"name": "search-tools",
"version": "2016.07.26-0",
"authors": [
"Adam Heath <doogie@brainfood.com>"
],
"main": [
"src/scripts/search-tools/*.js"
],
"ignore": [
"**/.*",
"node_modules",
"src/lib",
"src/scripts/**/*.spec.js",
"src/scripts/config.js",
"src/scripts/main.js"
],
"dependencies": {
"backbone": "",
"jquery": "",
"requirejs": "",
"underscore": ""
}
}
{
"name": "search-tools",
"version": "2016.07.26-0",
"dependencies": {
"requirejs": ""
},
"devDependencies": {
"grunt": "~0",
"grunt-monty-python": "git+http://gitlab.brainfood.com/brainfood/grunt-monty-python.git",
"rivets": ""
},
"engines": {
"node": ">=0.8.0"
}
}
/* global require:true */
var require;
require = (function() {
'use strict';
var require = {
baseUrl: 'scripts',
config: {
},
shim: {
backbone: {
deps: ['underscore'],
exports: 'Backbone',
},
underscore: {
exports: '_',
},
},
paths: {
backbone: '../lib/bower/backbone/backbone',
jquery: '../lib/bower/jquery/dist/jquery',
underscore: '../lib/bower/underscore/underscore',
},
};
return require;
})();
/* global require */
define(function(require) {
'use strict';
});
define(function(require) {
'use strict';
var _ = require('underscore');
var Backbone = require('backbone');
var Util = require('./Util');
var Paginator = Backbone.Model.extend({
defaults: function defaults() {
return {
hasNext: false,
hasNextJump: undefined,
hasPrevious: false,
hasPreviousJump: undefined,
leadingPageCount: 4,
nextJumpPage: undefined,
nextPage: undefined,
pages: [],
pageJump: 5,
previousJumpPage: undefined,
previousPage: undefined,
totalPages: 0,
trailingPageCount: 5,
};
},
initialize: function(data, options) {
var buildPages = _.bind(function buildPages() {
var source = this.get('source');
if (!source) {
return;
}
var currentPage = parseInt(source.get('currentPage'));
var pageSize = parseInt(source.get('pageSize'));
var totalCount = parseInt(source.get('totalCount'));
if (!totalCount) {
return;
}
var pages = [];
var totalPages = Math.floor((totalCount + pageSize - 1) / pageSize);
if (currentPage < 0) {
source.set('currentPage', 1);
return;
} else if (currentPage > totalPages) {
source.set('currentPage', totalPages);
return;
}
function addPage(self, i) {
pages.push({
current: i === currentPage,
jump: _.bind(function() {
this.get('source').set('currentPage', i);
return true;
}, self),
number: i,
});
}
var startAt = currentPage - this.get('leadingPageCount'), endAt = currentPage + this.get('trailingPageCount');
if (startAt < 1) {
endAt += (1 - startAt);
}
if (endAt > totalPages) {
startAt -= endAt - totalPages - 1;
endAt = totalPages + 1;
}
if (startAt < 1) {
startAt = 1;
}
for (var i = startAt; i < endAt; i++) {
addPage(this, i);
}
var hasPrevious = currentPage > 1;
var hasNext = currentPage < totalPages;
var pageJump = this.get('pageJump');
var nextJumpPage, previousJumpPage, hasNextJump, hasPreviousJump;
if (pageJump) {
nextJumpPage = currentPage + pageJump;
previousJumpPage = currentPage - pageJump;
hasNextJump = nextJumpPage < totalPages;
hasPreviousJump = previousJumpPage > 0;
} else {
hasNextJump = false;
hasPreviousJump = false;
}
this.set({
hasNext: hasNext,
hasNextJump: hasNextJump,
hasPrevious: hasPrevious,
hasPreviousJump: hasPreviousJump,
nextJumpPage: hasNextJump ? nextJumpPage : undefined,
nextPage: hasNext ? currentPage + 1 : undefined,
pages: pages,
previousJumpPage: hasNextJump ? previousJumpPage : undefined,
previousPage: hasPrevious ? currentPage - 1 : undefined,
totalPages: totalPages,
});
}, this);
this.on('change:leadingPageCount change:trailingPageCount', buildPages);
var installActions = _.bind(function installActions(eventName, nextName, actNextName, hasNextName, previousName, actPreviousName, hasPreviousName, pageCount) {
this.on(eventName, function() {
var hasNext = this.get(hasNextName);
var hasPrevious = this.get(hasPreviousName);
var next, previous;
if (hasNext) {
next = _.bind(function(e) {
Util.preventDefault(e);
var source = this.get('source');
source.set('currentPage', source.get('currentPage') + pageCount);
return false;
}, this);
} else {
next = Util.eventFalse;
}
if (hasPrevious) {
previous = _.bind(function(e) {
Util.preventDefault(e);
var source = this.get('source');
source.set('currentPage', source.get('currentPage') - pageCount);
return false;
}, this);
} else {
previous = Util.eventFalse;
}
this.set(nextName, next);
this.set(previousName, previous);
}, this);
this[actNextName] = _.bind(function() {
return this.get(nextName)();
}, this);
this[actPreviousName] = _.bind(function() {
return this.get(previousName)();
}, this);
this.trigger(eventName.split(' ')[0]);
}, this);
this.on('change:pageJump', function() {
var pageJump = this.get('pageJump');
installActions('change:hasNextJump change:hasPreviousJump', 'nextJump', 'actNextJump', 'hasNextJump', 'previousJump', 'actPreviousJump', 'hasPreviousJump', pageJump);
}, this);
installActions('change:hasNext change:hasPrevious', 'next', 'actNext', 'hasNext', 'previous', 'actPrevious', 'hasPrevious', 1);
this.on('change:source', function() {
var oldSource = this.previous('source');
if (oldSource) {
this.stopListening(oldSource);
}
this.listenTo(this.get('source'), 'change:pageSize change:currentPage change:totalCount', buildPages);
});
var r = Paginator.__super__.initialize.apply(this, arguments);
buildPages();
this.trigger('change:pageJump');
this.trigger('change:source');
return r;
}
});
return Paginator;
});
define(function(require) {
'use strict';
var _ = require('underscore');
var Backbone = require('backbone');
var Paginator = require('search-tools/Paginator');
describe('Paginator', function() {
it('loads', function() {
expect(Paginator).toBeDefined();
});
describe(':pages', function() {
it('default value is not shared globally', function() {
var p1 = new Paginator(), p2 = new Paginator();
expect(p1.get('pages')).not.toBe(p2.get('pages'));
});
});
describe('singleton', function() {
var p, source;
function checkHas(hasNext, hasNextJump, hasPrevious, hasPreviousJump) {
var wanted = {
hasNext: hasNext,
hasNextJump: hasNextJump,
hasPrevious: hasPrevious,
hasPreviousJump: hasPreviousJump,
};
it('has', function() {
var got = {
hasNext: p.get('hasNext'),
hasNextJump: p.get('hasNextJump'),
hasPrevious: p.get('hasPrevious'),
hasPreviousJump: p.get('hasPreviousJump'),
};
expect(got).toEqual(wanted);
});
}
function checkPages(wantedLength, offset, currentPage) {
var pages;
beforeEach(function() {
pages = p.get('pages');
});
//console.log(JSON.stringify(pages));
var wanted = { length: wantedLength, pages: [] };
for (var i = 0; i < wantedLength; i++) {
wanted.pages[i] = { current: i + 1 === currentPage, number: i + 1 + offset };
}
it('pages', function() {
pages = p.get('pages');
var got = { length: pages.length, pages: [] };
for (var i = 0; i < pages.length; i++) {
var page = pages[i];
got.pages[i] = { current: page.current, number: page.number };
}
expect(got).toEqual(wanted);
});
}
beforeEach(function() {
source = new Backbone.Model({currentPage: 1, pageSize: 10, totalCount: 0});
p = new Paginator({source: source});
});
describe('default settings', function() {
checkHas(false, undefined, false, undefined);
checkPages(0, 0, 1);
});
describe('35 items', function() {
beforeEach(function() {
source.set({totalCount:35});
});
describe('initial settings', function() {
checkHas(true, false, false, false);
checkPages(4, 0, 1);
});
describe('clamping', function() {
describe('set currentPage=5', function() {
beforeEach(function() {
source.set({currentPage: 5});
});
checkHas(false, false, true, false);
checkPages(4, 0, 4);
});
describe('set currentPage=-1', function() {
beforeEach(function() {
source.set({currentPage: -1});
});
checkHas(true, false, false, false);
checkPages(4, 0, 1);
});
});
describe('next[1]', function() {
beforeEach(function() {
p.actNext();
});
checkPages(4, 0, 2);
describe('previous', function() {
beforeEach(function() {
p.actPrevious();
});
checkHas(true, false, false, false);
checkPages(4, 0, 1);
});
describe('next[2]', function() {
beforeEach(function() {
p.actNext();
p.actNext();
});
checkHas(false, false, true, false);
checkPages(4, 0, 4);
describe('next[1] - clamp', function() {
beforeEach(function() {
p.actNext();
});
checkHas(false, false, true, false);
checkPages(4, 0, 4);
});
describe('page[0].jump', function() {
beforeEach(function() {
p.get('pages')[0].jump();
});
checkHas(true, false, false, false);
checkPages(4, 0, 1);
});
describe('page[3].jump', function() {
beforeEach(function() {
p.get('pages')[3].jump();
});
checkHas(false, false, true, false);
checkPages(4, 0, 4);
});
describe('decrease to 25 items', function() {
beforeEach(function() {
source.set({totalCount:25});
});
checkHas(false, false, true, false);
checkPages(3, 0, 3);
describe('increase to 150 items', function() {
beforeEach(function() {
source.set({totalCount:150});
});
checkHas(true, true, true, false);
checkPages(9, 0, 3);
});
});
});
});
describe('previous[1]', function() {
beforeEach(function() {
p.actPrevious();
});
checkHas(true, false, false, false);
checkPages(4, 0, 1);
});
});
describe('150 items', function() {
beforeEach(function() {
source.set({totalCount:150});
});
checkHas(true, true, false, false);
checkPages(9, 0, 1);
describe('page[7].jump', function() {
beforeEach(function() {
p.get('pages')[7].jump();
});
checkHas(true, true, true, true);
checkPages(9, 3, 5);
describe('previousJump', function() {
beforeEach(function() {
p.actPreviousJump();
});
checkHas(true, true, true, false);
checkPages(9, 0, 3);
});
});
});
describe('no page jump', function() {
beforeEach(function() {
p.set({pageJump: false});
source.set({totalCount:150});
});
checkHas(true, false, false, false);
checkPages(9, 0, 1);
});
});
});
});
define(function(require) {
'use strict';
function preventDefault(e) {
if (e) {
e.preventDefault();
}
}
function eventFalse(e) {
preventDefault(e);
return false;
}
return {
preventDefault: preventDefault,
eventFalse: eventFalse,
};
});
define(function(require) {
'use strict';
var _ = require('underscore');
var Util = require('search-tools/Util');
describe('Util', function() {
it('loads', function() {
expect(Util).toBeDefined();
});
it('exported items', function() {
var keys = {};
_.each(Util, function(value, key) {
keys[key] = true;
});
expect(keys).toEqual({
preventDefault: true,
eventFalse: true,
});
});
describe('methods', function() {
var e;
beforeEach(function() {
e = {preventDefault: jasmine.createSpy('preventDefault')};
});
it('preventDefault(null)', function() {
var r = Util.preventDefault(null);
expect(r).toBe(undefined);
expect(e.preventDefault).not.toHaveBeenCalled();
});
it('preventDefault(undefined)', function() {
var r = Util.preventDefault(undefined);
expect(r).toBe(undefined);
expect(e.preventDefault).not.toHaveBeenCalled();
});
it('preventDefault(e)', function() {
var r = Util.preventDefault(e);
expect(r).toBe(undefined);
expect(e.preventDefault).toHaveBeenCalled();
});
it('eventFalse(null)', function() {
var r = Util.eventFalse(null);
expect(r).toBe(false);
expect(e.preventDefault).not.toHaveBeenCalled();
});
it('eventFalse(undefined)', function() {
var r = Util.eventFalse(undefined);
expect(r).toBe(false);
expect(e.preventDefault).not.toHaveBeenCalled();
});
it('preventDefault(e)', function() {
var r = Util.eventFalse(e);
expect(r).toBe(false);
expect(e.preventDefault).toHaveBeenCalled();
});
});
});
});