2cc67ace by Adam Heath

More splitting, and more test specs.

1 parent ba0249c5
1 define(function(require) {
2 'use strict';
3 var _ = require('underscore');
4 var Backbone = require('backbone');
5 var Sort = require('./Sort');
6
7 function getItemKeyAccessor(item) {
8 return item.get('key');
9 }
10
11 function wrapComparatorForAllBeforeAfter(comparator, doBefore, doAfter) {
12 if (!doBefore && !doAfter) {
13 return comparator;
14 }
15 return function beforeAfterComparator(a, b) {
16 if (doBefore) {
17 if (a === 'before') {
18 return -1;
19 } else if (b === 'before') {
20 return 1;
21 }
22 }
23 if (doAfter) {
24 if (a === 'after') {
25 return 1;
26 } else if (b === 'after') {
27 return -1;
28 }
29 }
30 return comparator.call(this, a, b);
31 };
32 }
33 var Facet = Backbone.Model.extend({
34 defaults: function defaults() {
35 return {
36 formName: null,
37 query: null,
38 suggestions: [],
39 };
40 },
41 initialize: function(data, options) {
42 this.set('all', true);
43 this.on('change:queryMax change:queryMin', function() {
44 this.set('hasQuery', this.get('queryMin') !== undefined && this.get('queryMax') !== undefined);
45 }, this);
46 (function(self) {
47 var skipCallback;
48 self.on('item-change change:queryMax change:queryMin', function() {
49 switch (skipCallback) {
50 case 'change:checkedKeys':
51 case 'change:all':
52 return;
53 }
54 var checkedKeys = [];
55 this.get('items').each(function(facetItem) {
56 if (facetItem.get('checked')) {
57 checkedKeys.push(facetItem.get('key'));
58 }
59 });
60 var checkedCount = checkedKeys.length;
61 if (this.get('queryMin') !== undefined && this.get('queryMax') !== undefined) {
62 checkedCount++;
63 }
64 skipCallback = 'item-change';
65 try {
66 this.set({
67 all: checkedCount === 0,
68 checkedKeys: checkedKeys,
69
70 });
71 } finally {
72 skipCallback = null;
73 }
74 }, self);
75 self.on('change:all', function() {
76 switch (skipCallback) {
77 case 'change:checkedKeys':
78 case 'item-change':
79 return;
80 }
81 skipCallback = 'change:all';
82 try {
83 this.get('items').invoke('set', {checked: false});
84 this.set({
85 checkedKeys: [],
86 queryMax: undefined,
87 queryMin: undefined,
88 });
89 } finally {
90 skipCallback = null;
91 }
92 }, self);
93 self.on('change:checkedKeys', function() {
94 switch (skipCallback) {
95 case 'item-change':
96 case 'change:all':
97 return;
98 }
99 var checkedKeys = {};
100 _.each(this.get('checkedKeys'), function(value, i) {
101 checkedKeys[value] = true;
102 });
103 skipCallback = 'change:checkedKeys';
104 var checkedCount = 0;
105 if (this.get('queryMin') !== undefined && this.get('queryMax') !== undefined) {
106 checkedCount++;
107 }
108 try {
109 this.get('items').each(function(facetItem) {
110 var newChecked = checkedKeys[facetItem.get('key')];
111 var currentChecked = facetItem.get('checked');
112 if (newChecked !== currentChecked) {
113 facetItem.set('checked', newChecked);
114 }
115 if (facetItem.get('checked')) {
116 checkedCount++;
117 }
118 });
119 this.set({
120 all: checkedCount === 0,
121 });
122 } finally {
123 skipCallback = null;
124 }
125 }, self);
126 })(this);
127 var sortKeyExtractor = options.sortKeyExtractor;
128 if (!sortKeyExtractor) {
129 sortKeyExtractor = getItemKeyAccessor;
130 }
131 var comparator = options.comparator;
132 if (!comparator) {
133 comparator = Sort.standard;
134 } else if (typeof comparator === 'string') {
135 comparator = Sort[comparator];
136 }
137 switch (options.facetType) {
138 case 'year':
139 case 'range':
140 case 'interval':
141 comparator = wrapComparatorForAllBeforeAfter(comparator, ['all', 'before'].indexOf(options.other) !== -1, ['all', 'after'].indexOf(options.other) !== -1);
142 break;
143 }
144 var formatter = options.formatter;
145 if (!formatter) {
146 var labelMap = options.labelMap;
147 if (labelMap) {
148 formatter = function(item) {
149 var value = item.get('key');
150 var label = options.labelMap[value.toUpperCase()];
151 return label ? label : value;
152 };
153 } else {
154 formatter = getItemKeyAccessor;
155 }
156 }
157 this.formatter = formatter;
158 comparator = (function(comparator) {
159 return function facetItemValue(a, b) {
160 var keyA = sortKeyExtractor(a);
161 var keyB = sortKeyExtractor(b);
162 switch (this.get('orderByDirection')) {
163 case 'desc':
164 var tmp = keyA;
165 keyA = keyB;
166 keyB = tmp;
167 break;
168 }
169 return comparator.call(this, sortKeyExtractor(a), sortKeyExtractor(b));
170 };
171 })(comparator);
172 this.set('items', new ItemCollection([], {comparator: comparator}));
173 this.facetType = options.facetType;
174 this.facetStats = options.facetStats;
175 this.other = options.other;
176 this.facetField = options.facetField;
177 this.queryField = options.queryField;
178 this.queryValue = options.queryValue;
179 this.bins = options.bins;
180 switch (this.facetType) {
181 case 'year':
182 this.rangeStart = options.start;
183 this.rangeEnd = options.end;
184 this.rangeGap = '+' + (options.gap ? options.gap : 1) + 'YEAR';
185 break;
186 case 'range':
187 this.rangeStart = options.start;
188 this.rangeEnd = options.end;
189 this.rangeGap = options.gap;
190 break;
191 case 'field':
192 case 'year-field':
193 case 'interval':
194 break;
195 default:
196 var e = new Error('Unsupported facet type: ' + this.facetType);
197 e.facet = this;
198 throw e;
199 }
200 return Facet.__super__.initialize.apply(this, arguments);
201 },
202 /*
203 toJSON: function toJSON(options) {
204 if (!!options.facetSuggestions) {
205 return {
206 rows: 0,
207 facet: true,
208 wt: 'json',
209 q: '*:*',
210 'facet.contains': this.get('query'),
211 'facet.contains.ignoreCase': true,
212 'facet.field': this.queryField,
213 'facet.mincount': 1,
214 };
215 }
216 },
217 parse: function parse(data, options) {
218 if (!!options.facetSuggestions) {
219 var suggestions = [];
220 var key;
221 _.each(data.facet_counts.facet_fields[this.queryField], function(value, index) {
222 if (index % 2 === 0) {
223 key = value;
224 } else if (value > 0) {
225 suggestions.push({key: key, value: value});
226 }
227 });
228 return {
229 suggestions: suggestions,
230 };
231 }
232 return null;
233 },
234 */
235 });
236 var ItemCollection = Backbone.Collection.extend({
237 remove: function() {
238 }
239 });
240 var Item = Facet.Item = Backbone.Model.extend({
241 idAttribute: 'key',
242 defaults: {
243 checked: false,
244 hidden: false,
245 },
246 _initialize: function(data, options) {
247 this.on('add', function(model, parent, options) {
248 // added to a collection
249 this.on('change:checked', function() {
250 parent.trigger('item-change');
251 });
252 }, this);
253 return Item.__super__.initialize.apply(this, arguments);
254 }
255 });
256
257 return Facet;
258 });
...@@ -3,6 +3,8 @@ define(function(require) { ...@@ -3,6 +3,8 @@ define(function(require) {
3 var _ = require('underscore'); 3 var _ = require('underscore');
4 var Backbone = require('backbone'); 4 var Backbone = require('backbone');
5 var NestedModels = require('backbone-nested-models'); 5 var NestedModels = require('backbone-nested-models');
6 var Facet = require('./Facet');
7 var Sort = require('./Sort');
6 8
7 function getField(obj, key) { 9 function getField(obj, key) {
8 return obj[key]; 10 return obj[key];
...@@ -123,7 +125,7 @@ define(function(require) { ...@@ -123,7 +125,7 @@ define(function(require) {
123 if (item) { 125 if (item) {
124 item.set({hidden: value === 0, value: value}); 126 item.set({hidden: value === 0, value: value});
125 } else { 127 } else {
126 item = new Item({key: key, value: value}); 128 item = new Facet.Item({key: key, value: value});
127 item.on('change:checked', function() { 129 item.on('change:checked', function() {
128 this.trigger('item-change'); 130 this.trigger('item-change');
129 facet.trigger('item-change'); 131 facet.trigger('item-change');
...@@ -323,268 +325,8 @@ define(function(require) { ...@@ -323,268 +325,8 @@ define(function(require) {
323 return null; 325 return null;
324 }, 326 },
325 })); 327 }));
326 var Sort = Facets.Sort = { 328 Facets.Sort = Sort;
327 standard: function standardSort(a, b) { 329 Facets.Facet = Facet;
328 if (a < b) {
329 return -1;
330 } else if (a > b) {
331 return 1;
332 } else {
333 return 0;
334 }
335 },
336 date: function dateSort(a, b) {
337 return Sort.standard.call(this, a, b);
338 },
339 number: function numberSort(a, b) {
340 return Sort.standard.call(this, parseInt(a), parseInt(b));
341 },
342 };
343 function wrapComparatorForAllBeforeAfter(comparator, doBefore, doAfter) {
344 if (!doBefore && !doAfter) {
345 return comparator;
346 }
347 return function beforeAfterComparator(a, b) {
348 if (doBefore) {
349 if (a === 'before') {
350 return -1;
351 } else if (b === 'before') {
352 return 1;
353 }
354 }
355 if (doAfter) {
356 if (a === 'after') {
357 return 1;
358 } else if (b === 'after') {
359 return -1;
360 }
361 }
362 return comparator.call(this, a, b);
363 };
364 }
365 var Facet = Facets.Facet = Backbone.Model.extend({
366 defaults: function defaults() {
367 return {
368 formName: null,
369 query: null,
370 suggestions: [],
371 };
372 },
373 initialize: function(data, options) {
374 this.set('all', true);
375 this.on('change:queryMax change:queryMin', function() {
376 this.set('hasQuery', this.get('queryMin') !== undefined && this.get('queryMax') !== undefined);
377 }, this);
378 (function(self) {
379 var skipCallback;
380 self.on('item-change change:queryMax change:queryMin', function() {
381 switch (skipCallback) {
382 case 'change:checkedKeys':
383 case 'change:all':
384 return;
385 }
386 var checkedKeys = [];
387 this.get('items').each(function(facetItem) {
388 if (facetItem.get('checked')) {
389 checkedKeys.push(facetItem.get('key'));
390 }
391 });
392 var checkedCount = checkedKeys.length;
393 if (this.get('queryMin') !== undefined && this.get('queryMax') !== undefined) {
394 checkedCount++;
395 }
396 skipCallback = 'item-change';
397 try {
398 this.set({
399 all: checkedCount === 0,
400 checkedKeys: checkedKeys,
401
402 });
403 } finally {
404 skipCallback = null;
405 }
406 }, self);
407 self.on('change:all', function() {
408 switch (skipCallback) {
409 case 'change:checkedKeys':
410 case 'item-change':
411 return;
412 }
413 skipCallback = 'change:all';
414 try {
415 this.get('items').invoke('set', {checked: false});
416 this.set({
417 checkedKeys: [],
418 queryMax: undefined,
419 queryMin: undefined,
420 });
421 } finally {
422 skipCallback = null;
423 }
424 }, self);
425 self.on('change:checkedKeys', function() {
426 switch (skipCallback) {
427 case 'item-change':
428 case 'change:all':
429 return;
430 }
431 var checkedKeys = {};
432 _.each(this.get('checkedKeys'), function(value, i) {
433 checkedKeys[value] = true;
434 });
435 skipCallback = 'change:checkedKeys';
436 var checkedCount = 0;
437 if (this.get('queryMin') !== undefined && this.get('queryMax') !== undefined) {
438 checkedCount++;
439 }
440 try {
441 this.get('items').each(function(facetItem) {
442 var newChecked = checkedKeys[facetItem.get('key')];
443 var currentChecked = facetItem.get('checked');
444 if (newChecked !== currentChecked) {
445 facetItem.set('checked', newChecked);
446 }
447 if (facetItem.get('checked')) {
448 checkedCount++;
449 }
450 });
451 this.set({
452 all: checkedCount === 0,
453 });
454 } finally {
455 skipCallback = null;
456 }
457 }, self);
458 })(this);
459 var sortKeyExtractor = options.sortKeyExtractor;
460 if (!sortKeyExtractor) {
461 sortKeyExtractor = getItemKeyAccessor;
462 }
463 var comparator = options.comparator;
464 if (!comparator) {
465 comparator = Sort.standard;
466 } else if (typeof comparator === 'string') {
467 comparator = Sort[comparator];
468 }
469 switch (options.facetType) {
470 case 'year':
471 case 'range':
472 case 'interval':
473 comparator = wrapComparatorForAllBeforeAfter(comparator, ['all', 'before'].indexOf(options.other) !== -1, ['all', 'after'].indexOf(options.other) !== -1);
474 break;
475 }
476 var formatter = options.formatter;
477 if (!formatter) {
478 var labelMap = options.labelMap;
479 if (labelMap) {
480 formatter = function(item) {
481 var value = item.get('key');
482 var label = options.labelMap[value.toUpperCase()];
483 return label ? label : value;
484 };
485 } else {
486 formatter = getItemKeyAccessor;
487 }
488 }
489 this.formatter = formatter;
490 comparator = (function(comparator) {
491 return function facetItemValue(a, b) {
492 var keyA = sortKeyExtractor(a);
493 var keyB = sortKeyExtractor(b);
494 switch (this.get('orderByDirection')) {
495 case 'desc':
496 var tmp = keyA;
497 keyA = keyB;
498 keyB = tmp;
499 break;
500 }
501 return comparator.call(this, sortKeyExtractor(a), sortKeyExtractor(b));
502 };
503 })(comparator);
504 this.set('items', new ItemCollection([], {comparator: comparator}));
505 this.facetType = options.facetType;
506 this.facetStats = options.facetStats;
507 this.other = options.other;
508 this.facetField = options.facetField;
509 this.queryField = options.queryField;
510 this.queryValue = options.queryValue;
511 this.bins = options.bins;
512 switch (this.facetType) {
513 case 'year':
514 this.rangeStart = options.start;
515 this.rangeEnd = options.end;
516 this.rangeGap = '+' + (options.gap ? options.gap : 1) + 'YEAR';
517 break;
518 case 'range':
519 this.rangeStart = options.start;
520 this.rangeEnd = options.end;
521 this.rangeGap = options.gap;
522 break;
523 case 'field':
524 case 'year-field':
525 case 'interval':
526 break;
527 default:
528 var e = new Error('Unsupported facet type: ' + this.facetType);
529 e.facet = this;
530 throw e;
531 }
532 return Facet.__super__.initialize.apply(this, arguments);
533 },
534 /*
535 toJSON: function toJSON(options) {
536 if (!!options.facetSuggestions) {
537 return {
538 rows: 0,
539 facet: true,
540 wt: 'json',
541 q: '*:*',
542 'facet.contains': this.get('query'),
543 'facet.contains.ignoreCase': true,
544 'facet.field': this.queryField,
545 'facet.mincount': 1,
546 };
547 }
548 },
549 parse: function parse(data, options) {
550 if (!!options.facetSuggestions) {
551 var suggestions = [];
552 var key;
553 _.each(data.facet_counts.facet_fields[this.queryField], function(value, index) {
554 if (index % 2 === 0) {
555 key = value;
556 } else if (value > 0) {
557 suggestions.push({key: key, value: value});
558 }
559 });
560 return {
561 suggestions: suggestions,
562 };
563 }
564 return null;
565 },
566 */
567 });
568 var ItemCollection = Backbone.Collection.extend({
569 remove: function() {
570 }
571 });
572 var Item = Facet.Item = Backbone.Model.extend({
573 idAttribute: 'key',
574 defaults: {
575 checked: false,
576 hidden: false,
577 },
578 _initialize: function(data, options) {
579 this.on('add', function(model, parent, options) {
580 // added to a collection
581 this.on('change:checked', function() {
582 parent.trigger('item-change');
583 });
584 }, this);
585 return Item.__super__.initialize.apply(this, arguments);
586 }
587 });
588 330
589 return Facets; 331 return Facets;
590 }); 332 });
......
1 define(function(require) {
2 'use strict';
3
4 var Sort = {
5 standard: function standardSort(a, b) {
6 if (a < b) {
7 return -1;
8 } else if (a > b) {
9 return 1;
10 } else {
11 return 0;
12 }
13 },
14 date: function dateSort(a, b) {
15 return Sort.standard.call(this, a, b);
16 },
17 number: function numberSort(a, b) {
18 return Sort.standard.call(this, parseInt(a), parseInt(b));
19 },
20 };
21
22 return Sort;
23 });
1 define(function(require) {
2 'use strict';
3 var Facet = require('solr/model/Facet');
4
5 describe('Facet', function() {
6 it('loads', function() {
7 expect(Facet).toBeDefined();
8 });
9 });
10 });
1 define(function(require) {
2 'use strict';
3 var _ = require('underscore');
4 var Backbone = require('backbone');
5 var Facets = require('solr/model/Facets');
6
7 describe('Facets', function() {
8 it('loads', function() {
9 expect(Facets).toBeDefined();
10 });
11 });
12 });
1 define(function(require) {
2 'use strict';
3 var _ = require('underscore');
4 var Backbone = require('backbone');
5 var Sort = require('solr/model/Sort');
6
7 describe('Sort', function() {
8 it('loads', function() {
9 expect(Sort).toBeDefined();
10 });
11 it('standard(number)', function() {
12 var array = [5, 4, 2, 2, 3, 1, 5];
13 array.sort(Sort.standard);
14 expect(array).toEqual([1, 2, 2, 3, 4, 5, 5]);
15 });
16 it('standard(string)', function() {
17 var array = ['1', '500', '2', '400', '3', '300', '4', '200', '5', '100'];
18 array.sort(Sort.standard);
19 expect(array).toEqual(['1', '100', '2', '200', '3', '300', '4', '400', '5', '500']);
20 });
21 it('date', function() {
22 var array = [
23 '2016-02-05T13:25:06-0600',
24 '2015-02-05T13:25:06-0600',
25 '2014-02-05T13:25:06-0600',
26 '2013-02-05T13:25:06-0600',
27 '2012-02-05T13:25:06-0600',
28 '2011-02-05T13:25:06-0600',
29 ];
30 array.sort(Sort.date);
31 expect(array).toEqual([
32 '2011-02-05T13:25:06-0600',
33 '2012-02-05T13:25:06-0600',
34 '2013-02-05T13:25:06-0600',
35 '2014-02-05T13:25:06-0600',
36 '2015-02-05T13:25:06-0600',
37 '2016-02-05T13:25:06-0600',
38 ]);
39 });
40 it('number', function() {
41 var array = ['1', '500', '2', '400', '3', '300', '4', '200', '5', '100'];
42 array.sort(Sort.number);
43 expect(array).toEqual(['1', '2', '3', '4', '5', '100', '200', '300', '400', '500']);
44 });
45 });
46 });