Răsfoiți Sursa

Revert eslint changes, because they caused breakage.

Lauri Ojansivu 6 ani în urmă
părinte
comite
b015b5b724
1 a modificat fișierele cu 506 adăugiri și 443 ștergeri
  1. 506 443
      client/lib/filter.js

+ 506 - 443
client/lib/filter.js

@@ -3,9 +3,8 @@
 // RangeFilter, dateFilter, etc.). We then define a global `Filter` object whose
 // goal is to filter complete documents by using the local filters for each
 // fields.
-
 function showFilterSidebar() {
-  Sidebar.setView('filter');
+    Sidebar.setView('filter');
 }
 
 // Use a "set" filter for a field that is a set of documents uniquely
@@ -13,389 +12,446 @@ function showFilterSidebar() {
 // use "subField" for searching inside object Fields.
 // For instance '{ 'customFields._id': ['field1','field2']} (subField would be: _id)
 class SetFilter {
-  constructor(subField = '') {
-    this._dep = new Tracker.Dependency();
-    this._selectedElements = [];
-    this.subField = subField;
-  }
-
-  isSelected(val) {
-    this._dep.depend();
-    return this._selectedElements.indexOf(val) > -1;
-  }
-
-  add(val) {
-    if (this._indexOfVal(val) === -1) {
-      this._selectedElements.push(val);
-      this._dep.changed();
-      showFilterSidebar();
+    constructor(subField = '') {
+        this._dep = new Tracker.Dependency();
+        this._selectedElements = [];
+        this.subField = subField;
+    }
+
+    isSelected(val) {
+        this._dep.depend();
+        return this._selectedElements.indexOf(val) > -1;
+    }
+
+    add(val) {
+        if (this._indexOfVal(val) === -1) {
+            this._selectedElements.push(val);
+            this._dep.changed();
+            showFilterSidebar();
+        }
+    }
+
+    remove(val) {
+        const indexOfVal = this._indexOfVal(val);
+        if (this._indexOfVal(val) !== -1) {
+            this._selectedElements.splice(indexOfVal, 1);
+            this._dep.changed();
+        }
+    }
+
+    toggle(val) {
+        if (this._indexOfVal(val) === -1) {
+            this.add(val);
+        } else {
+            this.remove(val);
+        }
     }
-  }
 
-  remove(val) {
-    const indexOfVal = this._indexOfVal(val);
-    if (this._indexOfVal(val) !== -1) {
-      this._selectedElements.splice(indexOfVal, 1);
-      this._dep.changed();
+    reset() {
+        this._selectedElements = [];
+        this._dep.changed();
     }
-  }
 
-  toggle(val) {
-    if (this._indexOfVal(val) === -1) {
-      this.add(val);
-    } else {
-      this.remove(val);
+    _indexOfVal(val) {
+        return this._selectedElements.indexOf(val);
+    }
+
+    _isActive() {
+        this._dep.depend();
+        return this._selectedElements.length !== 0;
+    }
+
+    _getMongoSelector() {
+        this._dep.depend();
+        return {
+            $in: this._selectedElements
+        };
+    }
+
+    _getEmptySelector() {
+        this._dep.depend();
+        let includeEmpty = false;
+        this._selectedElements.forEach((el) => {
+            if (el === undefined) {
+                includeEmpty = true;
+            }
+        });
+        return includeEmpty ? {
+            $eq: []
+        } : null;
     }
-  }
-
-  reset() {
-    this._selectedElements = [];
-    this._dep.changed();
-  }
-
-  _indexOfVal(val) {
-    return this._selectedElements.indexOf(val);
-  }
-
-  _isActive() {
-    this._dep.depend();
-    return this._selectedElements.length !== 0;
-  }
-
-  _getMongoSelector() {
-    this._dep.depend();
-    return { $in: this._selectedElements };
-  }
-
-  _getEmptySelector() {
-    this._dep.depend();
-    let includeEmpty = false;
-    this._selectedElements.forEach((el) => {
-      if (el === undefined) {
-        includeEmpty = true;
-      }
-    });
-    return includeEmpty ? { $eq: [] } : null;
-  }
 }
 
 
 // Advanced filter forms a MongoSelector from a users String.
 // Build by: Ignatz 19.05.2018 (github feuerball11)
 class AdvancedFilter {
-  constructor() {
-    this._dep = new Tracker.Dependency();
-    this._filter = '';
-    this._lastValide = {};
-  }
-
-  set(str) {
-    this._filter = str;
-    this._dep.changed();
-  }
-
-  reset() {
-    this._filter = '';
-    this._lastValide = {};
-    this._dep.changed();
-  }
-
-  _isActive() {
-    this._dep.depend();
-    return this._filter !== '';
-  }
-
-  _filterToCommands() {
-    const commands = [];
-    let current = '';
-    let string = false;
-    let regex = false;
-    let wasString = false;
-    let ignore = false;
-    for (let i = 0; i < this._filter.length; i++) {
-      const char = this._filter.charAt(i);
-      if (ignore) {
-        ignore = false;
-        current += char;
-        continue;
-      }
-      if (char === '/'){
-        string = !string;
-        if (string) regex = true;
-        current += char;
-        continue;
-      }
-      if (char === '\'') {
-        string = !string;
-        if (string) wasString = true;
-        continue;
-      }
-      if (char === '\\' && !string) {
-        ignore = true;
-        continue;
-      }
-      if (char === ' ' && !string) {
-        commands.push({ 'cmd': current, 'string': wasString, regex});
-        wasString = false;
-        current = '';
-        continue;
-      }
-      current += char;
+    constructor() {
+        this._dep = new Tracker.Dependency();
+        this._filter = '';
+        this._lastValide = {};
     }
-    if (current !== '') {
-      commands.push({ 'cmd': current, 'string': wasString, regex});
+
+    set(str) {
+        this._filter = str;
+        this._dep.changed();
     }
-    return commands;
-  }
-
-  _fieldNameToId(field) {
-    const found = CustomFields.findOne({ 'name': field });
-    return found._id;
-  }
-
-  _fieldValueToId(field, value)
-  {
-    const found = CustomFields.findOne({ 'name': field });
-    if (found.settings.dropdownItems && found.settings.dropdownItems.length > 0)
-    {
-      for (let i = 0; i < found.settings.dropdownItems.length; i++)
-      {
-        if (found.settings.dropdownItems[i].name === value)
-        {
-          return found.settings.dropdownItems[i]._id;
-        }
-      }
+
+    reset() {
+        this._filter = '';
+        this._lastValide = {};
+        this._dep.changed();
     }
-    return value;
-  }
 
-  _arrayToSelector(commands) {
-    try {
-      //let changed = false;
-      this._processSubCommands(commands);
+    _isActive() {
+        this._dep.depend();
+        return this._filter !== '';
     }
-    catch (e) { return this._lastValide; }
-    this._lastValide = { $or: commands };
-    return { $or: commands };
-  }
-
-  _processSubCommands(commands) {
-    const subcommands = [];
-    let level = 0;
-    let start = -1;
-    for (let i = 0; i < commands.length; i++) {
-      if (commands[i].cmd) {
-        switch (commands[i].cmd) {
-        case '(':
-        {
-          level++;
-          if (start === -1) start = i;
-          continue;
-        }
-        case ')':
-        {
-          level--;
-          commands.splice(i, 1);
-          i--;
-          continue;
-        }
-        default:
-        {
-          if (level > 0) {
-            subcommands.push(commands[i]);
-            commands.splice(i, 1);
-            i--;
-            continue;
-          }
+
+    _filterToCommands() {
+        const commands = [];
+        let current = '';
+        let string = false;
+        let regex = false;
+        let wasString = false;
+        let ignore = false;
+        for (let i = 0; i < this._filter.length; i++) {
+            const char = this._filter.charAt(i);
+            if (ignore) {
+                ignore = false;
+                current += char;
+                continue;
+            }
+            if (char === '/') {
+                string = !string;
+                if (string) regex = true;
+                current += char;
+                continue;
+            }
+            if (char === '\'') {
+                string = !string;
+                if (string) wasString = true;
+                continue;
+            }
+            if (char === '\\' && !string) {
+                ignore = true;
+                continue;
+            }
+            if (char === ' ' && !string) {
+                commands.push({
+                    'cmd': current,
+                    'string': wasString,
+                    regex
+                });
+                wasString = false;
+                current = '';
+                continue;
+            }
+            current += char;
         }
+        if (current !== '') {
+            commands.push({
+                'cmd': current,
+                'string': wasString,
+                regex
+            });
         }
-      }
+        return commands;
     }
-    if (start !== -1) {
-      this._processSubCommands(subcommands);
-      if (subcommands.length === 1)
-        commands.splice(start, 0, subcommands[0]);
-      else
-        commands.splice(start, 0, subcommands);
+
+    _fieldNameToId(field) {
+        const found = CustomFields.findOne({
+            'name': field
+        });
+        return found._id;
     }
-    this._processConditions(commands);
-    this._processLogicalOperators(commands);
-  }
-
-  _processConditions(commands) {
-    for (let i = 0; i < commands.length; i++) {
-      if (!commands[i].string && commands[i].cmd) {
-        switch (commands[i].cmd) {
-        case '=':
-        case '==':
-        case '===':
-        {
-          const field = commands[i - 1].cmd;
-          const str = commands[i + 1].cmd;
-          if (commands[i + 1].regex)
-          {
-            const match = str.match(new RegExp('^/(.*?)/([gimy]*)$'));
-            let regex = null;
-            if (match.length > 2)
-              regex = new RegExp(match[1], match[2]);
-            else
-              regex = new RegExp(match[1]);
-            commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': regex };
-          }
-          else
-          {
-            commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': {$in: [this._fieldValueToId(field, str), parseInt(str, 10)]} };
-          }
-          commands.splice(i - 1, 1);
-          commands.splice(i, 1);
-          //changed = true;
-          i--;
-          break;
-        }
-        case '!=':
-        case '!==':
-        {
-          const field = commands[i - 1].cmd;
-          const str = commands[i + 1].cmd;
-          if (commands[i + 1].regex)
-          {
-            const match = str.match(new RegExp('^/(.*?)/([gimy]*)$'));
-            let regex = null;
-            if (match.length > 2)
-              regex = new RegExp(match[1], match[2]);
-            else
-              regex = new RegExp(match[1]);
-            commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $not: regex } };
-          }
-          else
-          {
-            commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $not: {$in: [this._fieldValueToId(field, str), parseInt(str, 10)]} } };
-          }
-          commands.splice(i - 1, 1);
-          commands.splice(i, 1);
-          //changed = true;
-          i--;
-          break;
-        }
-        case '>':
-        case 'gt':
-        case 'Gt':
-        case 'GT':
-        {
-          const field = commands[i - 1].cmd;
-          const str = commands[i + 1].cmd;
-          commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gt: parseInt(str, 10) } };
-          commands.splice(i - 1, 1);
-          commands.splice(i, 1);
-          //changed = true;
-          i--;
-          break;
-        }
-        case '>=':
-        case '>==':
-        case 'gte':
-        case 'Gte':
-        case 'GTE':
-        {
-          const field = commands[i - 1].cmd;
-          const str = commands[i + 1].cmd;
-          commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $gte:  parseInt(str, 10) } };
-          commands.splice(i - 1, 1);
-          commands.splice(i, 1);
-          //changed = true;
-          i--;
-          break;
-        }
-        case '<':
-        case 'lt':
-        case 'Lt':
-        case 'LT':
-        {
-          const field = commands[i - 1].cmd;
-          const str = commands[i + 1].cmd;
-          commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lt:  parseInt(str, 10) } };
-          commands.splice(i - 1, 1);
-          commands.splice(i, 1);
-          //changed = true;
-          i--;
-          break;
-        }
-        case '<=':
-        case '<==':
-        case 'lte':
-        case 'Lte':
-        case 'LTE':
-        {
-          const field = commands[i - 1].cmd;
-          const str = commands[i + 1].cmd;
-          commands[i] = { 'customFields._id': this._fieldNameToId(field), 'customFields.value': { $lte:  parseInt(str, 10) } };
-          commands.splice(i - 1, 1);
-          commands.splice(i, 1);
-          //changed = true;
-          i--;
-          break;
+
+    _fieldValueToId(field, value) {
+        const found = CustomFields.findOne({
+            'name': field
+        });
+        if (found.settings.dropdownItems && found.settings.dropdownItems.length > 0) {
+            for (let i = 0; i < found.settings.dropdownItems.length; i++) {
+                if (found.settings.dropdownItems[i].name === value) {
+                    return found.settings.dropdownItems[i]._id;
+                }
+            }
         }
+        return value;
+    }
+
+    _arrayToSelector(commands) {
+        try {
+            //let changed = false;
+            this._processSubCommands(commands);
+        } catch (e) {
+            return this._lastValide;
         }
-      }
+        this._lastValide = {
+            $or: commands
+        };
+        return {
+            $or: commands
+        };
     }
-  }
-
-  _processLogicalOperators(commands) {
-    for (let i = 0; i < commands.length; i++) {
-      if (!commands[i].string && commands[i].cmd) {
-        switch (commands[i].cmd) {
-        case 'or':
-        case 'Or':
-        case 'OR':
-        case '|':
-        case '||':
-        {
-          const op1 = commands[i - 1];
-          const op2 = commands[i + 1];
-          commands[i] = { $or: [op1, op2] };
-          commands.splice(i - 1, 1);
-          commands.splice(i, 1);
-          //changed = true;
-          i--;
-          break;
+
+    _processSubCommands(commands) {
+        const subcommands = [];
+        let level = 0;
+        let start = -1;
+        for (let i = 0; i < commands.length; i++) {
+            if (commands[i].cmd) {
+                switch (commands[i].cmd) {
+                case '(':
+                    {
+                        level++;
+                        if (start === -1) start = i;
+                        continue;
+                    }
+                case ')':
+                    {
+                        level--;
+                        commands.splice(i, 1);
+                        i--;
+                        continue;
+                    }
+                default:
+                    {
+                        if (level > 0) {
+                            subcommands.push(commands[i]);
+                            commands.splice(i, 1);
+                            i--;
+                            continue;
+                        }
+                    }
+                }
+            }
         }
-        case 'and':
-        case 'And':
-        case 'AND':
-        case '&':
-        case '&&':
-        {
-          const op1 = commands[i - 1];
-          const op2 = commands[i + 1];
-          commands[i] = { $and: [op1, op2] };
-          commands.splice(i - 1, 1);
-          commands.splice(i, 1);
-          //changed = true;
-          i--;
-          break;
+        if (start !== -1) {
+            this._processSubCommands(subcommands);
+            if (subcommands.length === 1)
+                commands.splice(start, 0, subcommands[0]);
+            else
+                commands.splice(start, 0, subcommands);
         }
-        case 'not':
-        case 'Not':
-        case 'NOT':
-        case '!':
-        {
-          const op1 = commands[i + 1];
-          commands[i] = { $not: op1 };
-          commands.splice(i + 1, 1);
-          //changed = true;
-          i--;
-          break;
+        this._processConditions(commands);
+        this._processLogicalOperators(commands);
+    }
+
+    _processConditions(commands) {
+        for (let i = 0; i < commands.length; i++) {
+            if (!commands[i].string && commands[i].cmd) {
+                switch (commands[i].cmd) {
+                case '=':
+                case '==':
+                case '===':
+                    {
+                        const field = commands[i - 1].cmd;
+                        const str = commands[i + 1].cmd;
+                        if (commands[i + 1].regex) {
+                            const match = str.match(new RegExp('^/(.*?)/([gimy]*)$'));
+                            let regex = null;
+                            if (match.length > 2)
+                                regex = new RegExp(match[1], match[2]);
+                            else
+                                regex = new RegExp(match[1]);
+                            commands[i] = {
+                                'customFields._id': this._fieldNameToId(field),
+                                'customFields.value': regex
+                            };
+                        } else {
+                            commands[i] = {
+                                'customFields._id': this._fieldNameToId(field),
+                                'customFields.value': {
+                                    $in: [this._fieldValueToId(field, str), parseInt(str, 10)]
+                                }
+                            };
+                        }
+                        commands.splice(i - 1, 1);
+                        commands.splice(i, 1);
+                        //changed = true;
+                        i--;
+                        break;
+                    }
+                case '!=':
+                case '!==':
+                    {
+                        const field = commands[i - 1].cmd;
+                        const str = commands[i + 1].cmd;
+                        if (commands[i + 1].regex) {
+                            const match = str.match(new RegExp('^/(.*?)/([gimy]*)$'));
+                            let regex = null;
+                            if (match.length > 2)
+                                regex = new RegExp(match[1], match[2]);
+                            else
+                                regex = new RegExp(match[1]);
+                            commands[i] = {
+                                'customFields._id': this._fieldNameToId(field),
+                                'customFields.value': {
+                                    $not: regex
+                                }
+                            };
+                        } else {
+                            commands[i] = {
+                                'customFields._id': this._fieldNameToId(field),
+                                'customFields.value': {
+                                    $not: {
+                                        $in: [this._fieldValueToId(field, str), parseInt(str, 10)]
+                                    }
+                                }
+                            };
+                        }
+                        commands.splice(i - 1, 1);
+                        commands.splice(i, 1);
+                        //changed = true;
+                        i--;
+                        break;
+                    }
+                case '>':
+                case 'gt':
+                case 'Gt':
+                case 'GT':
+                    {
+                        const field = commands[i - 1].cmd;
+                        const str = commands[i + 1].cmd;
+                        commands[i] = {
+                            'customFields._id': this._fieldNameToId(field),
+                            'customFields.value': {
+                                $gt: parseInt(str, 10)
+                            }
+                        };
+                        commands.splice(i - 1, 1);
+                        commands.splice(i, 1);
+                        //changed = true;
+                        i--;
+                        break;
+                    }
+                case '>=':
+                case '>==':
+                case 'gte':
+                case 'Gte':
+                case 'GTE':
+                    {
+                        const field = commands[i - 1].cmd;
+                        const str = commands[i + 1].cmd;
+                        commands[i] = {
+                            'customFields._id': this._fieldNameToId(field),
+                            'customFields.value': {
+                                $gte: parseInt(str, 10)
+                            }
+                        };
+                        commands.splice(i - 1, 1);
+                        commands.splice(i, 1);
+                        //changed = true;
+                        i--;
+                        break;
+                    }
+                case '<':
+                case 'lt':
+                case 'Lt':
+                case 'LT':
+                    {
+                        const field = commands[i - 1].cmd;
+                        const str = commands[i + 1].cmd;
+                        commands[i] = {
+                            'customFields._id': this._fieldNameToId(field),
+                            'customFields.value': {
+                                $lt: parseInt(str, 10)
+                            }
+                        };
+                        commands.splice(i - 1, 1);
+                        commands.splice(i, 1);
+                        //changed = true;
+                        i--;
+                        break;
+                    }
+                case '<=':
+                case '<==':
+                case 'lte':
+                case 'Lte':
+                case 'LTE':
+                    {
+                        const field = commands[i - 1].cmd;
+                        const str = commands[i + 1].cmd;
+                        commands[i] = {
+                            'customFields._id': this._fieldNameToId(field),
+                            'customFields.value': {
+                                $lte: parseInt(str, 10)
+                            }
+                        };
+                        commands.splice(i - 1, 1);
+                        commands.splice(i, 1);
+                        //changed = true;
+                        i--;
+                        break;
+                    }
+                }
+            }
         }
+    }
+
+    _processLogicalOperators(commands) {
+        for (let i = 0; i < commands.length; i++) {
+            if (!commands[i].string && commands[i].cmd) {
+                switch (commands[i].cmd) {
+                case 'or':
+                case 'Or':
+                case 'OR':
+                case '|':
+                case '||':
+                    {
+                        const op1 = commands[i - 1];
+                        const op2 = commands[i + 1];
+                        commands[i] = {
+                            $or: [op1, op2]
+                        };
+                        commands.splice(i - 1, 1);
+                        commands.splice(i, 1);
+                        //changed = true;
+                        i--;
+                        break;
+                    }
+                case 'and':
+                case 'And':
+                case 'AND':
+                case '&':
+                case '&&':
+                    {
+                        const op1 = commands[i - 1];
+                        const op2 = commands[i + 1];
+                        commands[i] = {
+                            $and: [op1, op2]
+                        };
+                        commands.splice(i - 1, 1);
+                        commands.splice(i, 1);
+                        //changed = true;
+                        i--;
+                        break;
+                    }
+                case 'not':
+                case 'Not':
+                case 'NOT':
+                case '!':
+                    {
+                        const op1 = commands[i + 1];
+                        commands[i] = {
+                            $not: op1
+                        };
+                        commands.splice(i + 1, 1);
+                        //changed = true;
+                        i--;
+                        break;
+                    }
+                }
+            }
         }
-      }
     }
-  }
 
-  _getMongoSelector() {
-    this._dep.depend();
-    const commands = this._filterToCommands();
-    return this._arrayToSelector(commands);
-  }
+    _getMongoSelector() {
+        this._dep.depend();
+        const commands = this._filterToCommands();
+        return this._arrayToSelector(commands);
+    }
 
 }
 
@@ -404,94 +460,101 @@ class AdvancedFilter {
 // the need to provide a list of `_fields`. We also should move methods into the
 // object prototype.
 Filter = {
-  // XXX I would like to rename this field into `labels` to be consistent with
-  // the rest of the schema, but we need to set some migrations architecture
-  // before changing the schema.
-  labelIds: new SetFilter(),
-  members: new SetFilter(),
-  customFields: new SetFilter('_id'),
-  advanced: new AdvancedFilter(),
-
-  _fields: ['labelIds', 'members', 'customFields'],
-
-  // We don't filter cards that have been added after the last filter change. To
-  // implement this we keep the id of these cards in this `_exceptions` fields
-  // and use a `$or` condition in the mongo selector we return.
-  _exceptions: [],
-  _exceptionsDep: new Tracker.Dependency(),
-
-  isActive() {
-    return _.any(this._fields, (fieldName) => {
-      return this[fieldName]._isActive();
-    }) || this.advanced._isActive();
-  },
-
-  _getMongoSelector() {
-    if (!this.isActive())
-      return {};
-
-    const filterSelector = {};
-    const emptySelector = {};
-    let includeEmptySelectors = false;
-    this._fields.forEach((fieldName) => {
-      const filter = this[fieldName];
-      if (filter._isActive()) {
-        if (filter.subField !== '') {
-          filterSelector[`${fieldName}.${filter.subField}`] = filter._getMongoSelector();
-        }
-        else {
-          filterSelector[fieldName] = filter._getMongoSelector();
+    // XXX I would like to rename this field into `labels` to be consistent with
+    // the rest of the schema, but we need to set some migrations architecture
+    // before changing the schema.
+    labelIds: new SetFilter(),
+    members: new SetFilter(),
+    customFields: new SetFilter('_id'),
+    advanced: new AdvancedFilter(),
+
+    _fields: ['labelIds', 'members', 'customFields'],
+
+    // We don't filter cards that have been added after the last filter change. To
+    // implement this we keep the id of these cards in this `_exceptions` fields
+    // and use a `$or` condition in the mongo selector we return.
+    _exceptions: [],
+    _exceptionsDep: new Tracker.Dependency(),
+
+    isActive() {
+        return _.any(this._fields, (fieldName) => {
+            return this[fieldName]._isActive();
+        }) || this.advanced._isActive();
+    },
+
+    _getMongoSelector() {
+        if (!this.isActive())
+            return {};
+
+        const filterSelector = {};
+        const emptySelector = {};
+        let includeEmptySelectors = false;
+        this._fields.forEach((fieldName) => {
+            const filter = this[fieldName];
+            if (filter._isActive()) {
+                if (filter.subField !== '') {
+                    filterSelector[`${fieldName}.${filter.subField}`] = filter._getMongoSelector();
+                } else {
+                    filterSelector[fieldName] = filter._getMongoSelector();
+                }
+                emptySelector[fieldName] = filter._getEmptySelector();
+                if (emptySelector[fieldName] !== null) {
+                    includeEmptySelectors = true;
+                }
+            }
+        });
+
+        const exceptionsSelector = {
+            _id: {
+                $in: this._exceptions
+            }
+        };
+        this._exceptionsDep.depend();
+
+        const selectors = [exceptionsSelector];
+
+        if (_.any(this._fields, (fieldName) => {
+                return this[fieldName]._isActive();
+            })) selectors.push(filterSelector);
+        if (includeEmptySelectors) selectors.push(emptySelector);
+        if (this.advanced._isActive()) selectors.push(this.advanced._getMongoSelector());
+
+        return {
+            $or: selectors
+        };
+    },
+
+    mongoSelector(additionalSelector) {
+        const filterSelector = this._getMongoSelector();
+        if (_.isUndefined(additionalSelector))
+            return filterSelector;
+        else
+            return {
+                $and: [filterSelector, additionalSelector]
+            };
+    },
+
+    reset() {
+        this._fields.forEach((fieldName) => {
+            const filter = this[fieldName];
+            filter.reset();
+        });
+        this.advanced.reset();
+        this.resetExceptions();
+    },
+
+    addException(_id) {
+        if (this.isActive()) {
+            this._exceptions.push(_id);
+            this._exceptionsDep.changed();
+            Tracker.flush();
         }
-        emptySelector[fieldName] = filter._getEmptySelector();
-        if (emptySelector[fieldName] !== null) {
-          includeEmptySelectors = true;
-        }
-      }
-    });
-
-    const exceptionsSelector = { _id: { $in: this._exceptions } };
-    this._exceptionsDep.depend();
-
-    const selectors = [exceptionsSelector];
-
-    if (_.any(this._fields, (fieldName) => {
-      return this[fieldName]._isActive();
-    })) selectors.push(filterSelector);
-    if (includeEmptySelectors) selectors.push(emptySelector);
-    if (this.advanced._isActive()) selectors.push(this.advanced._getMongoSelector());
-
-    return { $or: selectors };
-  },
-
-  mongoSelector(additionalSelector) {
-    const filterSelector = this._getMongoSelector();
-    if (_.isUndefined(additionalSelector))
-      return filterSelector;
-    else
-      return { $and: [filterSelector, additionalSelector] };
-  },
-
-  reset() {
-    this._fields.forEach((fieldName) => {
-      const filter = this[fieldName];
-      filter.reset();
-    });
-    this.advanced.reset();
-    this.resetExceptions();
-  },
-
-  addException(_id) {
-    if (this.isActive()) {
-      this._exceptions.push(_id);
-      this._exceptionsDep.changed();
-      Tracker.flush();
-    }
-  },
+    },
 
-  resetExceptions() {
-    this._exceptions = [];
-    this._exceptionsDep.changed();
-  },
+    resetExceptions() {
+        this._exceptions = [];
+        this._exceptionsDep.changed();
+    },
 };
 
-Blaze.registerHelper('Filter', Filter);
+Blaze.registerHelper('Filter', Filter);