<ul class="navigator-filter-select-list choices"></ul>
</script>
+<script id="choiceFilterTemplate" type="text/x-handlebars-template">
+ <ul class="navigator-filter-select-list choices"></ul>
+ <ul class="navigator-filter-select-list opposite"></ul>
+</script>
+
+<script id="choiceFilterItemTemplate" type="text/x-handlebars-template">
+ <li>
+ <label title="{{text}}"> {{! TODO: escape }}
+ <input type="checkbox" value="{{id}}" {{#if checked}}checked{{/if}}>
+ {{#if icon}}<i class="icon-{{icon}}"></i>{{/if}}
+ <span>
+ {{text}}
+ {{#if category}}
+ <br>
+ <span class="subtitle">{{category}}</span>
+ {{/if}}
+ </span>
+ </label>
+ </li>
+</script>
+
<script id="ajaxSelectFilterTemplate" type="text/template">
<div class="navigator-filter-search">
<input type="text">
</div>
- <ul class="navigator-filter-select-list selection"></ul>
<ul class="navigator-filter-select-list choices"></ul>
+ <ul class="navigator-filter-select-list opposite"></ul>
</script>
<script id="rangeFilterTemplate" type="text/template">
applyFavorite: function (e) {
var id = $j(e.target).data('id'),
- filter = new window.SS.FavoriteFilter({ id: id }),
+ filter = new FavoriteFilter({ id: id }),
app = this.options.filterView.options.app;
filter.fetch({
'navigator/filters/filter-bar',
'navigator/filters/base-filters',
'navigator/filters/checkbox-filters',
- 'navigator/filters/select-filters',
+ 'navigator/filters/choice-filters',
'navigator/filters/ajax-select-filters',
- 'navigator/filters/resolution-filters',
'navigator/filters/favorite-filters',
'navigator/filters/range-filters',
'navigator/filters/context-filters',
'handlebars-extensions'
],
- function (Backbone, Marionette, Handlebars, moment, Extra, FilterBar, BaseFilters, CheckboxFilterView, SelectFilters,
- AjaxSelectFilters, ResolutionFilterView, FavoriteFilters, RangeFilters, ContextFilterView,
+ function (Backbone, Marionette, Handlebars, moment, Extra, FilterBar, BaseFilters, CheckboxFilterView,
+ ChoiceFilters, AjaxSelectFilters, FavoriteFilters, RangeFilters, ContextFilterView,
ReadOnlyFilterView, ActionPlanFilterView, RuleFilterView) {
Handlebars.registerPartial('detailInnerTemplate', jQuery('#issue-detail-inner-template').html());
new BaseFilters.Filter({
name: window.SS.phrases.severity,
property: 'severities',
- type: SelectFilters.SelectFilterView,
+ type: ChoiceFilters.ChoiceFilterView,
enabled: true,
optional: false,
choices: {
new BaseFilters.Filter({
name: window.SS.phrases.status,
property: 'statuses',
- type: SelectFilters.SelectFilterView,
+ type: ChoiceFilters.ChoiceFilterView,
enabled: true,
optional: false,
choices: {
property: 'assignees',
type: AjaxSelectFilters.AssigneeFilterView,
enabled: true,
- optional: false
+ optional: false,
+ choices: {
+ '!assigned': window.SS.phrases.unassigned
+ }
}),
new BaseFilters.Filter({
name: window.SS.phrases.resolution,
property: 'resolutions',
- type: ResolutionFilterView,
+ type: ChoiceFilters.ChoiceFilterView,
enabled: true,
optional: false,
choices: {
- 'UNRESOLVED': window.SS.phrases.resolutions.UNRESOLVED,
+ '!resolved': window.SS.phrases.resolutions.UNRESOLVED,
'FALSE-POSITIVE': window.SS.phrases.resolutions['FALSE-POSITIVE'],
'FIXED': window.SS.phrases.resolutions.FIXED,
'REMOVED': window.SS.phrases.resolutions.REMOVED
type: ActionPlanFilterView,
enabled: false,
optional: true,
- projectFilter: projectFilter
+ projectFilter: projectFilter,
+ choices: {
+ '!planned': window.SS.phrases.unplanned
+ }
}),
new BaseFilters.Filter({
},
'backbone': {
exports: 'Backbone'
+ },
+ 'handlebars': {
+ exports: 'Handlebars'
}
}
'navigator/filters/filter-bar',
'navigator/filters/base-filters',
'navigator/filters/checkbox-filters',
- 'navigator/filters/select-filters',
+ 'navigator/filters/choice-filters',
'navigator/filters/ajax-select-filters',
'navigator/filters/favorite-filters',
'navigator/filters/range-filters',
'navigator/filters/string-filters',
'navigator/filters/metric-filters'
],
- function (Backbone, Marionette, FilterBar, BaseFilters, CheckboxFilterView, SelectFilters, AjaxSelectFilters,
+ function (Backbone, Marionette, FilterBar, BaseFilters, CheckboxFilterView, ChoiceFilters, AjaxSelectFilters,
FavoriteFilters, RangeFilters, StringFilterView, MetricFilterView) {
_.templateSettings = {
new BaseFilters.Filter({
name: window.SS.phrases.components,
property: 'qualifiers[]',
- type: SelectFilters.SelectFilterView,
+ type: ChoiceFilters.ChoiceFilterView,
enabled: true,
optional: false,
choices: window.SS.qualifiers,
new BaseFilters.Filter({
name: window.SS.phrases.alert,
property: 'alertLevels[]',
- type: SelectFilters.SelectFilterView,
+ type: ChoiceFilters.ChoiceFilterView,
enabled: false,
optional: true,
choices: {
new BaseFilters.Filter({
name: window.SS.phrases.language,
property: 'languages[]',
- type: SelectFilters.SelectFilterView,
+ type: ChoiceFilters.ChoiceFilterView,
enabled: false,
optional: true,
choices: window.SS.languages
-define(['backbone', 'navigator/filters/base-filters', 'navigator/filters/select-filters'], function (Backbone, BaseFilters, SelectFilters) {
+define(['backbone', 'navigator/filters/base-filters', 'navigator/filters/choice-filters'], function (Backbone, BaseFilters, ChoiceFilters) {
- var UNPLANNED = '<unplanned>';
-
-
- var ActionPlanDetailsFilterView = SelectFilters.DetailsSelectFilterView.extend({
-
- addToSelection: function(e) {
- var id = $j(e.target).val(),
- model = this.options.filterView.choices.findWhere({ id: id });
-
- if (this.model.get('multiple') && id !== UNPLANNED) {
- this.options.filterView.selection.add(model);
- this.options.filterView.choices.remove(model);
-
- var unplanned = this.options.filterView.selection.findWhere({ id: UNPLANNED });
- if (unplanned) {
- this.options.filterView.choices.add(unplanned);
- this.options.filterView.selection.remove(unplanned);
- }
- } else {
- this.options.filterView.choices.add(this.options.filterView.selection.models);
- this.options.filterView.choices.remove(model);
- this.options.filterView.selection.reset([model]);
- }
-
- this.updateValue();
- this.updateLists();
- },
-
-
- resetChoices: function() {
- if (this.options.filterView.selection.findWhere({ id: UNPLANNED })) {
- this.options.filterView.choices.reset([]);
- } else {
- this.options.filterView.choices.reset([{
- id: UNPLANNED,
- text: window.SS.phrases.unplanned,
- special: true
- }]);
- }
- }
- });
-
-
- return SelectFilters.SelectFilterView.extend({
+ return ChoiceFilters.ChoiceFilterView.extend({
initialize: function() {
- SelectFilters.SelectFilterView.prototype.initialize.call(this, {
- detailsView: ActionPlanDetailsFilterView
- });
+ ChoiceFilters.ChoiceFilterView.prototype.initialize.apply(this, arguments);
this.projectFilter = this.model.get('projectFilter');
this.listenTo(this.projectFilter, 'change:value', this.onChangeProjectFilter);
this.onChangeProjectFilter();
showDetails: function() {
if (!this.$el.is('.navigator-filter-inactive')) {
- SelectFilters.SelectFilterView.prototype.showDetails.apply(this, arguments);
+ ChoiceFilters.ChoiceFilterView.prototype.showDetails.apply(this, arguments);
}
},
title: window.SS.phrases.actionPlanNotAvailable
});
this.model.trigger('change:enabled');
- this.selection.reset([]);
this.choices.reset([]);
this.detailsView.updateLists();
this.detailsView.updateValue();
return plan.status === 'CLOSED';
}), 'name');
- that.selection.reset([]);
that.choices.reset(nonClosedActionPlans.map(function(plan) {
return {
id: plan.key,
category: plan.fDeadLine
}
}));
- that.choices.add(new Backbone.Model({
- id: UNPLANNED,
- text: window.SS.phrases.unplanned,
- special: true
- }));
-
+ _.each(that.model.get('choices'), function(v, k) {
+ that.choices.add(new Backbone.Model({ id: k, text: v }));
+ });
var value = that.model.get('value');
- if (that.choices && that.selection && value && value.length > 0) {
- value.forEach(function(id) {
- var model = that.choices.findWhere({ id: id });
- that.selection.add(model);
- that.choices.remove(model);
- });
- }
+ _.each(value, function(v) {
+ var cModel = that.choices.findWhere({ id: v });
+ cModel.set('checked', true);
+ });
that.detailsView.updateValue();
that.render();
},
- restoreFromQuery: function(q) {
- var param = _.findWhere(q, { key: this.model.get('property') }),
- planned = _.findWhere(q, { key: 'planned' });
-
- if (!!planned) {
- if (!param) {
- param = { value: UNPLANNED };
- } else {
- param.value += ',' + UNPLANNED;
- }
- }
-
- if (param && param.value) {
- this.model.set('enabled', true);
- this.restore(param.value);
- } else {
- this.clear();
- }
- },
-
-
restore: function(value) {
if (_.isString(value)) {
value = value.split(',');
}
- if (this.choices && this.selection && value.length > 0) {
+ if (this.choices && value.length > 0) {
this.model.set({ value: value, enabled: true });
this.onChangeProjectFilter();
} else {
this.clear();
}
- },
-
-
- formatValue: function() {
- var q = {};
- if (this.model.has('property') && this.model.has('value') && this.model.get('value').length > 0) {
- var assignees = _.without(this.model.get('value'), UNPLANNED);
- if (assignees.length > 0) {
- q[this.model.get('property')] = assignees.join(',');
- }
- if (this.model.get('value').length > assignees.length) {
- q.planned = false;
- }
- }
- return q;
}
});
-define(['backbone', 'navigator/filters/base-filters', 'navigator/filters/select-filters'], function (Backbone, BaseFilters, SelectFilters) {
+define(['backbone', 'navigator/filters/base-filters', 'navigator/filters/choice-filters'], function (Backbone, BaseFilters, ChoiceFilters) {
var PAGE_SIZE = 100,
- UNASSIGNED = '<unassigned>';
+ UNASSIGNED = '';
var Suggestions = Backbone.Collection.extend({
+ comparator: 'checked',
initialize: function() {
this.more = false;
- var AjaxSelectDetailsFilterView = SelectFilters.DetailsSelectFilterView.extend({
+ var AjaxSelectDetailsFilterView = ChoiceFilters.DetailsChoiceFilterView.extend({
template: '#ajaxSelectFilterTemplate',
+ listTemplate: '#choiceFilterTemplate',
- onRender: function() {
- this.resetChoices();
+ render: function() {
+ ChoiceFilters.DetailsChoiceFilterView.prototype.render.apply(this, arguments);
var that = this,
keyup = function(e) {
this.query = this.$('.navigator-filter-search input').val();
if (this.query.length > 1) {
this.$el.addClass('fetching');
+ var selected = that.options.filterView.getSelected();
this.options.filterView.choices.fetch({
data: {
s: this.query,
ps: PAGE_SIZE
},
success: function() {
- var choices = that.options.filterView.choices.reject(function(item) {
- return that.options.filterView.selection.findWhere({ id: item.get('id') });
+ selected.each(function(item) {
+ that.options.filterView.choices.unshift(item);
+ });
+ _.each(that.model.get('choices'), function(v, k) {
+ that.options.filterView.choices.add(new Backbone.Model({ id: k, text: v }));
});
- that.options.filterView.choices.reset(choices);
that.updateLists();
that.$el.removeClass('fetching');
}
resetChoices: function() {
- this.options.filterView.choices.reset([]);
+ var that = this;
+ this.options.filterView.choices.reset(this.options.filterView.choices.filter(function(item) {
+ return item.get('checked');
+ }));
+ _.each(this.model.get('choices'), function(v, k) {
+ that.options.filterView.choices.add(new Backbone.Model({ id: k, text: v }));
+ });
},
onShow: function() {
- SelectFilters.DetailsSelectFilterView.prototype.onShow.apply(this, arguments);
+ ChoiceFilters.DetailsChoiceFilterView.prototype.onShow.apply(this, arguments);
+ this.resetChoices();
+ this.render();
this.$('.navigator-filter-search input').focus();
}
- var AjaxSelectFilterView = SelectFilters.SelectFilterView.extend({
+ var AjaxSelectFilterView = ChoiceFilters.ChoiceFilterView.extend({
isDefaultValue: function() {
- return this.selection.length === 0;
+ return this.getSelected().length === 0;
},
value = value.split(',');
}
- if (this.choices && this.selection && value.length > 0) {
- this.selection.reset([]);
- this.model.set({
- value: value,
- enabled: true
- });
-
+ if (this.choices && value.length > 0) {
+ this.model.set({ value: value, enabled: true });
if (_.isArray(param.text) && param.text.length === value.length) {
this.restoreFromText(value, param.text);
} else {
restoreFromText: function(value, text) {
var that = this;
_.each(value, function(v, i) {
- that.selection.add(new Backbone.Model({
+ that.choices.add(new Backbone.Model({
id: v,
- text: text[i]
+ text: text[i],
+ checked: true
}));
});
this.onRestore(value);
clear: function() {
this.model.unset('value');
- if (this.selection && this.choices) {
+ if (this.choices) {
this.choices.reset([]);
- this.selection.reset([]);
- this.detailsView.updateLists();
}
- this.renderBase();
+ this.render();
},
var ComponentFilterView = AjaxSelectFilterView.extend({
initialize: function() {
- BaseFilters.BaseFilterView.prototype.initialize.call(this, {
+ AjaxSelectFilterView.prototype.initialize.call(this, {
detailsView: AjaxSelectDetailsFilterView
});
-
- this.selection = new ComponentSuggestions();
this.choices = new ComponentSuggestions();
},
detailsView: AjaxSelectDetailsFilterView
});
- this.selection = new ProjectSuggestions();
this.choices = new ProjectSuggestions();
},
data: { resource: v }
})
.done(function (r) {
- that.selection.add(new Backbone.Model({
+ that.choices.add(new Backbone.Model({
id: r[0].key,
- text: r[0].name
+ text: r[0].name,
+ checked: true
}));
});
}
- var AssigneeDetailsFilterView = AjaxSelectDetailsFilterView.extend({
-
- addToSelection: function(e) {
- var id = $j(e.target).val(),
- model = this.options.filterView.choices.findWhere({ id: id });
-
- if (this.model.get('multiple') && id !== UNASSIGNED) {
- this.options.filterView.selection.add(model);
- this.options.filterView.choices.remove(model);
-
- var unassigned = this.options.filterView.selection.findWhere({ id: UNASSIGNED });
- if (unassigned) {
- this.options.filterView.choices.add(unassigned);
- this.options.filterView.selection.remove(unassigned);
- }
- } else {
- this.options.filterView.choices.add(this.options.filterView.selection.models);
- this.options.filterView.choices.remove(model);
- this.options.filterView.selection.reset([model]);
- }
-
- this.updateValue();
- this.updateLists();
- },
-
-
- resetChoices: function() {
- if (this.options.filterView.selection.findWhere({ id: UNASSIGNED })) {
- this.options.filterView.choices.reset([]);
- } else {
- this.options.filterView.choices.reset([{
- id: UNASSIGNED,
- text: window.SS.phrases.unassigned,
- special: true
- }]);
- }
- },
-
-
- onShow: function() {
- AjaxSelectDetailsFilterView.prototype.onShow.apply(this, arguments);
- this.$('.navigator-filter-search input').focus();
- }
-
- });
-
-
-
var AssigneeFilterView = AjaxSelectFilterView.extend({
initialize: function() {
BaseFilters.BaseFilterView.prototype.initialize.call(this, {
- detailsView: AssigneeDetailsFilterView
+ detailsView: AjaxSelectDetailsFilterView
});
- this.selection = new UserSuggestions();
this.choices = new UserSuggestions();
},
-
- restoreFromQuery: function(q) {
- var param = _.findWhere(q, { key: this.model.get('property') }),
- assigned = _.findWhere(q, { key: 'assigned' });
-
- if (!!assigned) {
- if (!param) {
- param = { value: UNASSIGNED };
- } else {
- param.value += ',' + UNASSIGNED;
- }
- }
-
- if (param && param.value) {
- this.model.set('enabled', true);
- this.restore(param.value, param);
- } else {
- this.clear();
- }
- },
-
-
- restoreFromText: function(value) {
- if (_.indexOf(value, UNASSIGNED) !== -1) {
- this.choices.reset([]);
- }
-
- AjaxSelectFilterView.prototype.restoreFromText.apply(this, arguments);
- },
-
-
- restoreByRequests: function(value) {
- if (_.indexOf(value, UNASSIGNED) !== -1) {
- this.selection.add(new Backbone.Model({
- id: UNASSIGNED,
- text: window.SS.phrases.unassigned,
- special: true
- }));
- this.choices.reset([]);
- value = _.reject(value, function(k) { return k === UNASSIGNED; });
- }
-
- AjaxSelectFilterView.prototype.restoreByRequests.call(this, value);
- },
-
-
createRequest: function(v) {
var that = this;
return $j
data: { logins: v }
})
.done(function (r) {
- that.selection.add(new Backbone.Model({
+ that.choices.add(new Backbone.Model({
id: r.users[0].login,
- text: r.users[0].name + ' (' + r.users[0].login + ')'
+ text: r.users[0].name + ' (' + r.users[0].login + ')',
+ checked: true
}));
});
- },
-
-
- clear: function() {
- this.model.unset('value');
- if (this.selection && this.choices) {
- this.detailsView.resetChoices();
- this.selection.reset([]);
- }
- this.renderBase();
- this.detailsView.updateLists();
- },
-
-
- formatValue: function() {
- var q = {};
- if (this.model.has('property') && this.model.has('value') && this.model.get('value').length > 0) {
- var assignees = _.without(this.model.get('value'), UNASSIGNED);
- if (assignees.length > 0) {
- q[this.model.get('property')] = assignees.join(',');
- }
- if (this.model.get('value').length > assignees.length) {
- q.assigned = false;
- }
- }
- return q;
}
});
data: { logins: v }
})
.done(function (r) {
- that.selection.add(new Backbone.Model({
+ that.choices.add(new Backbone.Model({
id: r.users[0].login,
- text: r.users[0].name + ' (' + r.users[0].login + ')'
+ text: r.users[0].name + ' (' + r.users[0].login + ')',
+ checked: true
}));
});
}
--- /dev/null
+define(['handlebars', 'navigator/filters/base-filters'], function (Handlebars, BaseFilters) {
+
+ var DetailsChoiceFilterView = BaseFilters.DetailsFilterView.extend({
+ template: Handlebars.compile(jQuery('#choiceFilterTemplate').html()),
+ itemTemplate: Handlebars.compile(jQuery('#choiceFilterItemTemplate').html()),
+
+
+ events: function() {
+ return {
+ 'change input[type=checkbox]': 'onCheck'
+ };
+ },
+
+
+ render: function() {
+ BaseFilters.DetailsFilterView.prototype.render.apply(this, arguments);
+ this.updateLists();
+ },
+
+
+ renderList: function(collection, selector) {
+ var that = this,
+ container = this.$(selector);
+
+ container.empty().toggleClass('hidden', collection.length === 0);
+ collection.each(function(item) {
+ container.append(that.itemTemplate(item.toJSON()));
+ });
+ },
+
+
+ updateLists: function() {
+ var choices = new Backbone.Collection(this.options.filterView.choices.reject(function(item) {
+ return item.get('id')[0] === '!';
+ })),
+ opposite = new Backbone.Collection(this.options.filterView.choices.filter(function(item) {
+ return item.get('id')[0] === '!';
+ }));
+
+ this.renderList(choices, '.choices');
+ this.renderList(opposite, '.opposite');
+
+ var current = this.currentChoice || 0;
+ this.updateCurrent(current);
+ },
+
+
+ onCheck: function(e) {
+ var checkbox = jQuery(e.target),
+ id = checkbox.val(),
+ checked = checkbox.prop('checked');
+
+ if (this.model.get('multiple')) {
+ if (checkbox.closest('.opposite').length > 0) {
+ this.options.filterView.choices.reject(function(item) {
+ return item.get('id')[0] === '!'
+ }).forEach(function(item) {
+ item.set('checked', false);
+ });
+ } else {
+ this.options.filterView.choices.filter(function(item) {
+ return item.get('id')[0] === '!'
+ }).forEach(function(item) {
+ item.set('checked', false);
+ });
+ }
+ } else {
+ this.options.filterView.choices.each(function(item) {
+ item.set('checked', false);
+ });
+ }
+
+ this.options.filterView.choices.get(id).set('checked', checked);
+ this.updateValue();
+ this.updateLists();
+ },
+
+
+ updateValue: function() {
+ this.model.set('value', this.options.filterView.getSelected().map(function(m) {
+ return m.get('id');
+ }));
+ },
+
+
+ updateCurrent: function(index) {
+ this.currentChoice = index;
+ this.$('label').removeClass('current')
+ .eq(this.currentChoice).addClass('current');
+ },
+
+
+ onShow: function() {
+ this.bindedOnKeyDown = _.bind(this.onKeyDown, this);
+ $j('body').on('keydown', this.bindedOnKeyDown);
+ },
+
+
+ onHide: function() {
+ $j('body').off('keydown', this.bindedOnKeyDown);
+ },
+
+
+ onKeyDown: function(e) {
+ switch (e.keyCode) {
+ case 38:
+ e.preventDefault();
+ this.selectPrevChoice();
+ break;
+ case 40:
+ e.preventDefault();
+ this.selectNextChoice();
+ break;
+ case 13:
+ e.preventDefault();
+ this.selectCurrent();
+ break;
+ }
+ },
+
+
+ selectNextChoice: function() {
+ if (this.$('label').length > this.currentChoice + 1) {
+ this.updateCurrent(this.currentChoice + 1);
+ this.scrollNext();
+ }
+ },
+
+
+ scrollNext: function() {
+ var currentLabel = this.$('label').eq(this.currentChoice);
+ if (currentLabel.length > 0) {
+ var list = currentLabel.closest('ul'),
+ labelPos = currentLabel.offset().top - list.offset().top + list.scrollTop(),
+ deltaScroll = labelPos - list.height() + currentLabel.outerHeight();
+
+ if (deltaScroll > 0) {
+ list.scrollTop(deltaScroll);
+ }
+ }
+ },
+
+
+ selectPrevChoice: function() {
+ if (this.currentChoice > 0) {
+ this.updateCurrent(this.currentChoice - 1);
+ this.scrollPrev();
+ }
+ },
+
+
+ scrollPrev: function() {
+ var currentLabel = this.$('label').eq(this.currentChoice);
+ if (currentLabel.length > 0) {
+ var list = currentLabel.closest('ul'),
+ labelPos = currentLabel.offset().top - list.offset().top;
+
+ if (labelPos < 0) {
+ list.scrollTop(list.scrollTop() + labelPos);
+ }
+ }
+ },
+
+
+ selectCurrent: function() {
+ this.$('label').eq(this.currentChoice).click();
+ },
+
+
+ serializeData: function() {
+ return _.extend({}, this.model.toJSON(), {
+ choices: new Backbone.Collection(this.options.filterView.choices.reject(function(item) {
+ return item.get('id')[0] === '!';
+ })).toJSON(),
+ opposite: new Backbone.Collection(this.options.filterView.choices.filter(function(item) {
+ return item.get('id')[0] === '!';
+ })).toJSON()
+ });
+ }
+
+ });
+
+
+
+ var ChoiceFilterView = BaseFilters.BaseFilterView.extend({
+
+ initialize: function(options) {
+ BaseFilters.BaseFilterView.prototype.initialize.call(this, {
+ detailsView: (options && options.detailsView) ? options.detailsView : DetailsChoiceFilterView
+ });
+
+ var index = 0,
+ icons = this.model.get('choiceIcons');
+
+ this.choices = new Backbone.Collection(
+ _.map(this.model.get('choices'), function(value, key) {
+ var model = new Backbone.Model({
+ id: key,
+ text: value,
+ checked: false,
+ index: index++
+ });
+
+ if (icons && icons[key]) {
+ model.set('icon', icons[key]);
+ }
+
+ return model;
+ }), { comparator: 'index' }
+ );
+ },
+
+
+ getSelected: function() {
+ return this.choices.filter(function(m) {
+ return m.get('checked');
+ });
+ },
+
+
+ renderInput: function() {
+ var input = $j('<select>')
+ .prop('name', this.model.get('property'))
+ .prop('multiple', true)
+ .css('display', 'none');
+ this.choices.each(function(item) {
+ var option = $j('<option>')
+ .prop('value', item.get('id'))
+ .prop('selected', item.get('checked'))
+ .text(item.get('text'));
+ option.appendTo(input);
+ });
+ input.appendTo(this.$el);
+ },
+
+
+ renderValue: function() {
+ var value = this.getSelected().map(function(item) {
+ return item.get('text');
+ }),
+ defaultValue = this.model.has('defaultValue') ?
+ this.model.get('defaultValue') :
+ this.model.get('multiple') ? window.SS.phrases.all : window.SS.phrases.any;
+
+ return this.isDefaultValue() ? defaultValue : value.join(', ');
+ },
+
+
+ isDefaultValue: function() {
+ var selected = this.getSelected();
+ return selected.length === 0;
+ },
+
+
+ disable: function() {
+ this.choices.each(function(item) {
+ item.set('checked', false);
+ });
+ BaseFilters.BaseFilterView.prototype.disable.apply(this, arguments);
+ },
+
+
+ restoreFromQuery: function(q) {
+ var param = _.findWhere(q, { key: this.model.get('property') });
+
+ if (this.choices) {
+ this.choices.forEach(function(item) {
+ if (item.get('id')[0] === '!') {
+ var x = _.findWhere(q, { key: item.get('id').substr(1) });
+ if (x) {
+ if (!param) {
+ param = { value: item.get('id') };
+ } else {
+ param.value += ',' + item.get('id');
+ }
+ }
+ }
+ });
+ }
+
+ if (param && param.value) {
+ this.model.set('enabled', true);
+ this.restore(param.value, param);
+ } else {
+ this.clear();
+ }
+ },
+
+
+ restore: function(value) {
+ if (_.isString(value)) {
+ value = value.split(',');
+ }
+
+ if (this.choices && value.length > 0) {
+ var that = this;
+
+ that.choices.each(function(item) {
+ item.set('checked', false);
+ });
+
+ _.each(value, function(v) {
+ var cModel = that.choices.findWhere({ id: v });
+ cModel.set('checked', true);
+ });
+
+ this.model.set({
+ value: value,
+ enabled: true
+ });
+
+ this.render();
+ } else {
+ this.clear();
+ }
+ },
+
+
+ clear: function() {
+ if (this.choices) {
+ this.choices.each(function(item) {
+ item.set('checked', false);
+ });
+ }
+ this.model.unset('value');
+ this.detailsView.render();
+ if (this.detailsView.updateCurrent) {
+ this.detailsView.updateCurrent(0);
+ }
+ },
+
+
+ formatValue: function() {
+ var q = {};
+ if (this.model.has('property') && this.model.has('value') && this.model.get('value').length > 0) {
+ var opposite = _.filter(this.model.get('value'), function(item) {
+ return item[0] === '!';
+ });
+ if (opposite.length > 0) {
+ opposite.forEach(function(item) {
+ q[item.substr(1)] = false;
+ });
+ } else {
+ q[this.model.get('property')] = this.model.get('value').join(',');
+ }
+ }
+ return q;
+ }
+
+ });
+
+
+
+ /*
+ * Export public classes
+ */
+
+ return {
+ DetailsChoiceFilterView: DetailsChoiceFilterView,
+ ChoiceFilterView: ChoiceFilterView
+ };
+
+});
-define(['backbone', 'backbone.marionette', 'navigator/filters/base-filters', 'navigator/filters/select-filters'], function (Backbone, Marionette, BaseFilters, SelectFilters) {
+define(['backbone', 'backbone.marionette', 'navigator/filters/base-filters', 'navigator/filters/choice-filters'], function (Backbone, Marionette, BaseFilters, ChoiceFilters) {
var DetailsFavoriteFilterView = BaseFilters.DetailsFilterView.extend({
template: '#detailsFavoriteFilterTemplate',
- var FavoriteFilterView = SelectFilters.SelectFilterView.extend({
+ var FavoriteFilterView = ChoiceFilters.ChoiceFilterView.extend({
template: '#favoriteFilterTemplate',
className: 'navigator-filter navigator-filter-favorite',
initialize: function() {
- BaseFilters.BaseFilterView.prototype.initialize.call(this, {
+ ChoiceFilters.ChoiceFilterView.prototype.initialize.call(this, {
detailsView: DetailsFavoriteFilterView
});
},
-define(['navigator/filters/base-filters', 'navigator/filters/select-filters'], function (BaseFilters, SelectFilters) {
+define(['navigator/filters/base-filters', 'navigator/filters/choice-filters'], function (BaseFilters, ChoiceFilters) {
var DetailsMoreCriteriaFilterView = BaseFilters.DetailsFilterView.extend({
template: '#detailsMoreCriteriaFilterTemplate',
- var MoreCriteriaFilterView = SelectFilters.SelectFilterView.extend({
+ var MoreCriteriaFilterView = ChoiceFilters.ChoiceFilterView.extend({
template: '#moreCriteriaFilterTemplate',
className: 'navigator-filter navigator-filter-more-criteria',
initialize: function() {
- BaseFilters.BaseFilterView.prototype.initialize.call(this, {
+ ChoiceFilters.ChoiceFilterView.prototype.initialize.call(this, {
detailsView: DetailsMoreCriteriaFilterView
});
},
+++ /dev/null
-define(['navigator/filters/base-filters', 'navigator/filters/select-filters'], function (BaseFilters, SelectFilters) {
-
- var UNRESOLVED = 'UNRESOLVED';
-
- var ResolutionDetailFilterView = SelectFilters.DetailsSelectFilterView.extend({
-
- addToSelection: function(e) {
- var id = $j(e.target).val(),
- model = this.options.filterView.choices.findWhere({ id: id });
-
- if (this.model.get('multiple') && id !== UNRESOLVED) {
- this.options.filterView.selection.add(model);
- this.options.filterView.choices.remove(model);
-
- var unresolved = this.options.filterView.selection.findWhere({ id: UNRESOLVED });
- if (unresolved) {
- this.options.filterView.choices.add(unresolved);
- this.options.filterView.selection.remove(unresolved);
- }
- } else {
- this.options.filterView.choices.add(this.options.filterView.selection.models);
- this.options.filterView.choices.remove(model);
- this.options.filterView.selection.reset([model]);
- }
-
- this.updateValue();
- this.updateLists();
- }
-
- });
-
-
- return SelectFilters.SelectFilterView.extend({
-
- initialize: function() {
- SelectFilters.SelectFilterView.prototype.initialize.call(this, {
- detailsView: ResolutionDetailFilterView
- });
-
- var unresolved = this.choices.findWhere({ id: UNRESOLVED });
- unresolved.set('special', true);
- },
-
-
- restoreFromQuery: function(q) {
- var param = _.findWhere(q, { key: this.model.get('property') }),
- resolved = _.findWhere(q, { key: 'resolved' });
-
- if (!!resolved) {
- if (!param) {
- param = { value: UNRESOLVED };
- } else {
- param.value += ',' + UNRESOLVED;
- }
- }
-
- if (param && param.value) {
- this.model.set('enabled', true);
- this.restore(param.value, param);
- } else {
- this.clear();
- }
- },
-
-
- formatValue: function() {
- var q = {},
- resolutions = this.model.get('value');
- if (this.model.has('property') && resolutions) {
- var unresolved = resolutions.indexOf(UNRESOLVED) !== -1;
-
- if (unresolved) {
- q.resolved = false;
- } else {
- q[this.model.get('property')] = resolutions.join(',');
- }
- }
- return q;
- }
-
- });
-
-});
return AjaxSelectFilters.AjaxSelectFilterView.extend({
initialize: function() {
- BaseFilters.BaseFilterView.prototype.initialize.call(this, {
+ AjaxSelectFilters.AjaxSelectFilterView.prototype.initialize.call(this, {
detailsView: AjaxSelectFilters.AjaxSelectDetailsFilterView
});
- this.selection = new RuleSuggestions();
this.choices = new RuleSuggestions();
},
+++ /dev/null
-define(['navigator/filters/base-filters'], function (BaseFilters) {
-
- var DetailsSelectFilterView = BaseFilters.DetailsFilterView.extend({
- template: '#selectFilterTemplate',
- itemTemplate: '#selectFilterItemTemplate',
-
-
- events: function() {
- return {
- 'change .choices input[type=checkbox]': 'addToSelection',
- 'change .selection input[type=checkbox]': 'removeFromSelection'
- };
- },
-
-
- render: function() {
- BaseFilters.DetailsFilterView.prototype.render.apply(this, arguments);
- this.updateLists();
- },
-
-
- renderList: function(collection, selector, checked) {
- var that = this,
- container = this.$(selector),
- t = _.template($j(this.itemTemplate).html());
-
- container.empty().toggleClass('hidden', collection.length === 0);
- collection.each(function(item) {
- container.append(t(_.extend(
- {
- item: item.toJSON(),
- checked: checked
- }, that.model.toJSON())));
- });
- },
-
-
- updateLists: function() {
- this.renderList(this.options.filterView.selection, '.selection', true);
- this.renderList(this.options.filterView.choices, '.choices', false);
-
- var current = this.currentChoice || 0;
- this.updateCurrent(current);
- },
-
-
- addToSelection: function(e) {
- var id = $j(e.target).val(),
- model = this.options.filterView.choices.findWhere({ id: id });
-
- if (this.model.get('multiple')) {
- this.options.filterView.selection.add(model);
- this.options.filterView.choices.remove(model);
- } else {
- this.options.filterView.choices.add(this.options.filterView.selection.models);
- this.options.filterView.choices.remove(model);
- this.options.filterView.selection.reset([model]);
- }
-
- this.updateValue();
- this.updateLists();
- },
-
-
- removeFromSelection: function(e) {
- var id = $j(e.target).val(),
- model = this.options.filterView.selection.findWhere({ id: id });
-
- this.options.filterView.choices.add(model);
- this.options.filterView.selection.remove(model);
-
- this.updateValue();
- this.updateLists();
- },
-
-
- updateValue: function() {
- this.model.set('value', this.options.filterView.selection.map(function(m) {
- return m.get('id');
- }));
- },
-
-
- updateCurrent: function(index) {
- this.currentChoice = index;
- this.$('label').removeClass('current')
- .eq(this.currentChoice).addClass('current');
- },
-
-
- onShow: function() {
- this.bindedOnKeyDown = _.bind(this.onKeyDown, this);
- $j('body').on('keydown', this.bindedOnKeyDown);
- },
-
-
- onHide: function() {
- $j('body').off('keydown', this.bindedOnKeyDown);
- },
-
-
- onKeyDown: function(e) {
- switch (e.keyCode) {
- case 38:
- e.preventDefault();
- this.selectPrevChoice();
- break;
- case 40:
- e.preventDefault();
- this.selectNextChoice();
- break;
- case 13:
- e.preventDefault();
- this.selectCurrent();
- break;
- }
- },
-
-
- selectNextChoice: function() {
- if (this.$('label').length > this.currentChoice + 1) {
- this.updateCurrent(this.currentChoice + 1);
- this.scrollNext();
- }
- },
-
-
- scrollNext: function() {
- var currentLabel = this.$('label').eq(this.currentChoice);
- if (currentLabel.length > 0) {
- var list = currentLabel.closest('ul'),
- labelPos = currentLabel.offset().top - list.offset().top + list.scrollTop(),
- deltaScroll = labelPos - list.height() + currentLabel.outerHeight();
-
- if (deltaScroll > 0) {
- list.scrollTop(deltaScroll);
- }
- }
- },
-
-
- selectPrevChoice: function() {
- if (this.currentChoice > 0) {
- this.updateCurrent(this.currentChoice - 1);
- this.scrollPrev();
- }
- },
-
-
- scrollPrev: function() {
- var currentLabel = this.$('label').eq(this.currentChoice);
- if (currentLabel.length > 0) {
- var list = currentLabel.closest('ul'),
- labelPos = currentLabel.offset().top - list.offset().top;
-
- if (labelPos < 0) {
- list.scrollTop(list.scrollTop() + labelPos);
- }
- }
- },
-
-
- selectCurrent: function() {
- this.$('label').eq(this.currentChoice).click();
- },
-
-
- serializeData: function() {
- return _.extend({}, this.model.toJSON(), {
- selection: this.options.filterView.selection.toJSON(),
- choices: this.options.filterView.choices.toJSON()
- });
- }
- });
-
-
-
- var SelectFilterView = BaseFilters.BaseFilterView.extend({
- className: 'navigator-filter',
-
-
- initialize: function(options) {
- BaseFilters.BaseFilterView.prototype.initialize.call(this, {
- detailsView: (options && options.detailsView) ? options.detailsView : DetailsSelectFilterView
- });
-
-
- this.selection = new Backbone.Collection([], { comparator: 'index' });
-
- var index = 0,
- icons = this.model.get('choiceIcons');
-
- this.choices = new Backbone.Collection(
- _.map(this.model.get('choices'), function(value, key) {
- var model = new Backbone.Model({
- id: key,
- text: value,
- index: index++
- });
-
- if (icons && icons[key]) {
- model.set('icon', icons[key]);
- }
-
- return model;
- }), { comparator: 'index' }
- );
- },
-
-
- renderInput: function() {
- var input = $j('<select>')
- .prop('name', this.model.get('property'))
- .prop('multiple', true)
- .css('display', 'none');
- this.selection.each(function(item) {
- var option = $j('<option>')
- .prop('value', item.get('id'))
- .prop('selected', true)
- .text(item.get('text'));
- option.appendTo(input);
- });
- this.choices.each(function(item) {
- var option = $j('<option>')
- .prop('value', item.get('id'))
- .text(item.get('text'));
- option.appendTo(input);
- });
- input.appendTo(this.$el);
- },
-
-
- renderValue: function() {
- var value = this.selection.map(function(item) {
- return item.get('text');
- }),
- defaultValue = this.model.has('defaultValue') ?
- this.model.get('defaultValue') :
- this.model.get('multiple') ? window.SS.phrases.all : window.SS.phrases.any;
-
- return this.isDefaultValue() ? defaultValue : value.join(', ');
- },
-
-
- isDefaultValue: function() {
- return this.selection.length === 0 || this.choices.length === 0;
- },
-
-
- disable: function() {
- this.choices.add(this.selection.models);
- this.selection.reset([]);
- BaseFilters.BaseFilterView.prototype.disable.apply(this, arguments);
- },
-
-
- restore: function(value) {
- if (_.isString(value)) {
- value = value.split(',');
- }
-
- if (this.choices && this.selection && value.length > 0) {
- var that = this;
- this.choices.add(this.selection.models);
- this.selection.reset([]);
-
- _.each(value, function(v) {
- var cModel = that.choices.findWhere({ id: v });
-
- if (cModel) {
- that.selection.add(cModel);
- that.choices.remove(cModel);
- }
- });
-
- this.detailsView.updateLists();
-
- this.model.set({
- value: value,
- enabled: true
- });
-
- this.renderBase();
- } else {
- this.clear();
- }
- },
-
-
- clear: function() {
- var that = this;
- if (this.selection && this.choices) {
- this.selection.each(function(m) {
- that.choices.add(m);
- });
- this.selection.reset([]);
- }
- this.model.unset('value');
- this.detailsView.render();
- if (this.detailsView.updateCurrent) {
- this.detailsView.updateCurrent(0);
- }
- },
-
-
- formatValue: function() {
- var q = {};
- if (this.model.has('property') && this.model.has('value') && this.model.get('value').length > 0) {
- q[this.model.get('property')] = this.model.get('value').join(',');
- }
- return q;
- }
-
- });
-
-
-
- /*
- * Export public classes
- */
-
- return {
- DetailsSelectFilterView: DetailsSelectFilterView,
- SelectFilterView: SelectFilterView
- };
-
-});