/js/model/appmodel.js
JavaScript | 231 lines | 170 code | 15 blank | 46 comment | 20 complexity | 8e4f54253a85cb18ebbc7ef3aba8531f MD5 | raw file
- // Groups of properties in the leftmost property list
- var Groups = Backbone.Collection.extend({
- initialize: function (solrInterface) {
- var self = this;
- solrInterface.on('change:fieldgroups',function (model,groups) {
- groups = removeNullElementsInGroups(groups);
- self.reset(groups);
- });
- }
- });
- // List of document results from a query
- var Results = Backbone.Collection.extend({
- initialize: function (solrInterface) {
- var self = this;
- solrInterface.on('change:docs',function (model,articles) {
- self.reset(articles);
- });
- }
- });
- // List of filters; maintaining only id's
- // The rest is kept in the attribute model
- var Filters = Backbone.Collection.extend({
- // Move a filter to a new pos
- move: function (id,pos) {
- this.remove(id);
- this.add({id:id},pos);
- },
- appendId: function (id) {
- this.add({id:id});
- },
- removeId: function(id) {
- this.remove({id:id});
- }
- });
- // The overall model
- // Most (but not all) of the event propagation goes through here
- var ApplicationModel = Backbone.Model.extend({
-
- // defaultHighlightedAttributes should be
- // moved into a configuration module
- defaultHighlightedAttributes:["name"],
-
- initialize: function (solrInterface,urlData) {
-
- this.set('attributes',new Attributes({},solrInterface));
- this.set('results',new Results(solrInterface));
- this.set('groupings',new Groups(solrInterface));
-
- this.set('filters',new Filters());
- this.set('query',new Query());
- this.set('solrInterface',solrInterface);
-
- this.set('global-tools',GlobalTools(this));
-
- // The 'fetch-needed' event will trigger the processed
- // query to be submitted to the solr interface
- this.on('fetch-needed',
- _.bind(this._postQuery,this));
- this.get('query').set('phrase',urlData.search);
-
- // When attribute focus is changed, we need to
- // de-focus the old attribute item
- this.listenTo(this.get('attributes'),'focus-change',
- _.bind(function(newInFocus_Id) {
- // Put other attributes out of focus
- var old_focused_id = this.get('attribute_in_focus');
- if(old_focused_id && (old_focused_id != newInFocus_Id)){
- var old_focused = this.get('attributes').get(old_focused_id);
- if(old_focused){old_focused.set('in_focus',false);}
- }
- this.set('attribute_in_focus',newInFocus_Id);
- },this));
-
- // If an attribute wants to become a filter, it has to be added in
- // a few places
- this.listenTo(this.get('attributes'),'attribute-wants-to-be-filter',
- _.bind(function(id) {
- this.get('query').addFacetField(id);
- this.get('filters').appendId(id);
- this.trigger('fetch-needed',this);
- },this));
-
- // If we delete a filter, we need to remove it from filters and query,
- // And we need to make and submit a new query
- this.listenTo(this.get('attributes'),'attribute-dont-want-to-be-filter',
- _.bind(function(id) {
- if(!id){return;}
- if(!this.get('filters').get(id)){return;}
- this.get('attributes').get(id).dropValues();
- this.get('filters').removeId(id);
- this.get('query').removeFacetField(id);
- // Triggers the filterprocessor
- this.get('filters').trigger('selection-change',this.get('filters'));
- this.trigger('fetch-needed',this);
- },this));
- // query Solr for the initial state
- // (without trying to process filters)
- this.trigger('fetch-needed',this);
-
- // The filters should be processed by a filter processor whenever
- // a selection-change happens
- var filterProcessor = new FilterProcessor({model:this});
- this.listenTo(this.get('filters'),'selection-change',
- _.bind(filterProcessor.processFilters,filterProcessor));
- },
- // tell the solr interface to send the query to Solr
- _postQuery: function () {
- this.get('solrInterface').placeQuery(this.get('query'));
- },
- // Toggle selection of a value of an attribute and let
- // listeners know it happened
- selectValue: function (parentAttrName,valueName) {
- this.get('attributes').get(parentAttrName).selectValue(valueName);
- this.get('filters').trigger('selection-change',this.get('filters'));
- },
- // Get field names that are to be used as columns for the
- // result list
- getHighlightedAttributes: function () {
- if(this.get('query').get('sortingFields')){
- return this.defaultHighlightedAttributes
- .concat(this.get('query').get('sortingFields'));
- } else {
- return this.defaultHighlightedAttributes;
- }
- },
- // Make the query ask for sorted results
- // and trigger a new fetch to Solr
- cycleGlobalSorting: function () {
- this.get('query').cycleSorting();
- this.triggerReload();
- },
- toggleFuzziness: function () {
- this.get('query').toggleFuzziness();
- this.triggerReload();
- },
- // Select a range of values on a enumerable facet
- // without triggering a reload
- selectRangeSilently: function (attribute,range) {
- attribute.selectRangeSilently(range);
- },
- // Trigger filters to be processed and a Solr fetch to happen
- triggerReload: function () {
- this.get('filters').trigger('selection-change',this.get('filters'));
- }
- });
- // Query object, maintaining processed information
- // on what is to be requested from Solr
- var Query = Backbone.Model.extend({
- initialize: function () {
- this.set('sorting',false);
- this.set('fuzziness',false);
- this.set('fuzzy-params',[10000,0.1]);
- this.set('facet_fields',{});
- },
- // sorting is based on selected filters
- cycleSorting: function () {
- if(!this.get('sorting')){
- this.set('sorting','asc');
- } else if (this.get('sorting')=='asc'){
- this.set('sorting','desc');
- } else if (this.get('sorting')=='desc'){
- this.set('sorting',false);
- }
- },
- toggleFuzziness: function () {
- this.set('fuzziness',!this.get('fuzziness'));
- },
- // Convert this query object into a
- // Solr query object
- prepare: function () {
- assert(this instanceof Query);
- var self = this;
- var prepared_query = {
- q:self._getStatement()
- };
- if(this.get('facet_fields')){
- var facetFields = _.keys(self.get('facet_fields'));
- // the propertyNames field is needed for sorting in the
- // grouping component
- facetFields.push("propertyNames");
- prepared_query = _.extend(prepared_query,{
- 'facet' : true,
- 'facet.mincount' : 1,
- 'facet.limit' : 40,
- 'facet.field' : facetFields
- });
- }
- if(this.get('sorting') && this.get('sortingFields') && (this.get('sortingFields').length>0)){
- prepared_query = _.extend(prepared_query,{
- sort:self._getSortingExpression()
- });
- }
- return prepared_query;
- },
- //
- _getStatement: function () {
- if(this.get('filterStatement')){
- return '('+this.get('phrase')+') AND '+this.get('filterStatement');
- }
- return this.get('phrase');
- },
- // Defining the part of the query that determine sorting order
- // of the result. Should only be used when score sorting is not
- // desired
- _getSortingExpression: function() {
- var self = this;
- return _.map(this.get('sortingFields'),function (fieldName) {
- return fieldName+' '+self.get('sorting');
- }).join(', ');
- },
- // Maintaining a redundant store on what
- // property fields are used as filters
- addFacetField: function (name) {
- if(!this.get('facet_fields')[name]){
- this.get('facet_fields')[name] = true;
- this.trigger('change',this);
- }
- },
- removeFacetField: function(name) {
- if(this.get('facet_fields')[name]){
- var facet_fields = this.get('facet_fields');
- delete facet_fields[name];
- this.set('facet_fields',facet_fields);
- }
- }
- });