Added filters to xosTable and tested
diff --git a/views/ngXosLib/.eslintrc b/views/ngXosLib/.eslintrc
index f9a952f..cf02168 100644
--- a/views/ngXosLib/.eslintrc
+++ b/views/ngXosLib/.eslintrc
@@ -24,7 +24,6 @@
         "indent": [2, 2],
         "no-irregular-whitespace": 1,
         "eol-last": 0,
-        "max-nested-callbacks": [2, 4],
         "comma-spacing": [1, {"before": false, "after": true}],
         "no-trailing-spaces": [1, { skipBlankLines: true }],
         "no-unused-vars": [1, {"vars": "all", "args": "after-used"}],
diff --git a/views/ngXosLib/gulp/ngXosHelpers.js b/views/ngXosLib/gulp/ngXosHelpers.js
index c9915e2..f046681 100644
--- a/views/ngXosLib/gulp/ngXosHelpers.js
+++ b/views/ngXosLib/gulp/ngXosHelpers.js
@@ -63,7 +63,7 @@
       styles: [
         'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css',
       ],
-      html5Mode: true,
+      html5Mode: false,
       title: 'XOS Helpers documentation',
       startPage: '/module',
     }
@@ -109,7 +109,6 @@
     gulp.watch(files, ['makeDocs']);
 
     gulp.watch(files, function(){
-      console.log('Reload');
       browserSync.reload();
     });
   })
diff --git a/views/ngXosLib/karma.conf.js b/views/ngXosLib/karma.conf.js
index ae486dc..e3c1cbb 100644
--- a/views/ngXosLib/karma.conf.js
+++ b/views/ngXosLib/karma.conf.js
@@ -86,7 +86,7 @@
 
     // start these browsers
     // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
-    browsers: ['PhantomJS', 'Chrome'],
+    browsers: ['PhantomJS'],
 
 
     // Continuous Integration mode
diff --git a/views/ngXosLib/xos/core/xoslib/static/js/vendor/ngXosHelpers.js b/views/ngXosLib/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
index 6aecaf1..2fc5ba7 100644
--- a/views/ngXosLib/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
+++ b/views/ngXosLib/xos/core/xoslib/static/js/vendor/ngXosHelpers.js
@@ -24,24 +24,46 @@
   * @name xos.uiComponents.table.directive:xosTable
   * @restrict E
   * @description The xos-table directive
+  * @param {Object} config The configuration for the component.
+  * ```
+  * {
+  *   columns: [
+  *     {
+  *       label: 'Human readable name',
+  *       prop: 'Property to read in the model object'
+  *     }
+  *   ],
+  *   classes: 'table table-striped table-bordered',
+  *   actions: [ // if defined add an action column
+        {
+          label: 'delete',
+          icon: 'remove', // refers to bootstraps glyphicon
+          cb: (user) => { // receive the model
+            console.log(user);
+          },
+          color: 'red'
+        }
+      ]
+  * }
+  * ```
+  * @param {Array} data The data that should be rendered
   * @element ANY
   * @scope
   * @example
-  <example module="sampleModule">
+  <example module="sampleModule1">
   <file name="index.html">
     <div ng-controller="SampleCtrl1 as vm">
       <xos-table data="vm.data" config="vm.config"></xos-table>
-      </xos-table>
     </div>
   </file>
   <file name="script.js">
-    angular.module('sampleModule', ['xos.uiComponents.table'])
+    angular.module('sampleModule1', ['xos.uiComponents.table'])
     .controller('SampleCtrl1', function(){
       this.config = {
         columns: [
           {
-            label: 'First Name',
-            prop: 'name'
+            label: 'First Name', // column title
+            prop: 'name' // property to read in the data array
           },
           {
             label: 'Last Name',
@@ -62,36 +84,35 @@
     });
   </file>
   </example>
-   <example module="sampleModule">
+  <example module="sampleModule2">
   <file name="index.html">
     <div ng-controller="SampleCtrl2 as vm">
       <xos-table data="vm.data" config="vm.config"></xos-table>
-      </xos-table>
     </div>
   </file>
   <file name="script.js">
-    angular.module('sampleModule', ['xos.uiComponents.table'])
+    angular.module('sampleModule2', ['xos.uiComponents.table'])
     .controller('SampleCtrl2', function(){
       this.config = {
         columns: [
           {
-            label: 'First Name',
-            prop: 'name'
+            label: 'First Name', // column title
+            prop: 'name' // property to read in the data array
           },
           {
             label: 'Last Name',
             prop: 'lastname'
           }
         ],
-        classes: 'table table-striped table-condensed',
-        actions: [
+        classes: 'table table-striped table-condensed', // table classes, default to `table table-striped table-bordered`
+        actions: [ // if defined add an action column
           {
-            label: 'delete',
-            icon: 'remove',
-            cb: (user) => {
+            label: 'delete', // label
+            icon: 'remove', // icons, refers to bootstraps glyphicon
+            cb: (user) => { // callback, get feeded with the full object
               console.log(user);
             },
-            color: 'red'
+            color: 'red' // icon color
           }
         ]
       };
@@ -117,7 +138,7 @@
         data: '=',
         config: '='
       },
-      template: '\n          <!-- <pre>{{vm.data | json}}</pre> -->\n          <table ng-class="vm.classes" ng-show="vm.data.length > 0">\n            <thead>\n              <tr>\n                <th ng-repeat="col in vm.columns">{{col.label}}</th>\n                <th ng-if="vm.config.actions">Actions</th>\n              </tr>\n            </thead>\n            <tbody>\n              <tr ng-repeat="item in vm.data">\n                <td ng-repeat="col in vm.columns">{{item[col.prop]}}</td>\n                <td ng-if="vm.config.actions">\n                  <i\n                    ng-repeat="action in vm.config.actions"\n                    ng-click="action.cb(item)"\n                    class="glyphicon glyphicon-{{action.icon}}"\n                    style="color: {{action.color}};"></i>\n                </td>\n              </tr>\n            </tbody>\n          </table>\n        ',
+      template: '\n          <!-- <pre>{{vm.data | json}}</pre> -->\n          <table ng-class="vm.classes" ng-show="vm.data.length > 0">\n            <thead>\n              <tr>\n                <th ng-repeat="col in vm.columns">{{col.label}}</th>\n                <th ng-if="vm.config.actions">Actions</th>\n              </tr>\n            </thead>\n            <tbody>\n              <tr ng-repeat="item in vm.data">\n                <td ng-repeat="col in vm.columns">{{item[col.prop]}}</td>\n                <td ng-if="vm.config.actions">\n                  <a href=""\n                    ng-repeat="action in vm.config.actions"\n                    ng-click="action.cb(item)"\n                    title="action.label">\n                    <i\n                      class="glyphicon glyphicon-{{action.icon}}"\n                      style="color: {{action.color}};"></i>\n                  </a>\n                </td>\n              </tr>\n            </tbody>\n          </table>\n        ',
       bindToController: true,
       controllerAs: 'vm',
       controller: function controller() {
diff --git a/views/ngXosLib/xosHelpers/spec/ui/table.test.js b/views/ngXosLib/xosHelpers/spec/ui/table.test.js
index e4c33f1..d83b6f6 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/table.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/table.test.js
@@ -31,51 +31,129 @@
         expect(errorFunctionWrapper).toThrow(new Error('[xosTable] Please provide a columns list in the configuration'));
       }));
 
-    });
+      describe('when basicly configured', function() {
+        var scope, element, isolatedScope;
 
-    describe('when correctly configured', function() {
-      var scope, element, isolatedScope;
+        beforeEach(inject(function ($compile, $rootScope) {
+          scope = $rootScope.$new();
 
-      beforeEach(inject(function ($compile, $rootScope) {
-        scope = $rootScope.$new();
+          scope.config = {
+            columns: [
+              {
+                label: 'Label 1',
+                prop: 'label-1'
+              },
+              {
+                label: 'Label 2',
+                prop: 'label-2'
+              }
+            ]
+          };
 
-        scope.config = {
-          columns: [
+          scope.data = [
             {
-              label: 'Label 1',
-              prop: 'label-1'
+              'label-1': 'Sample 1.1',
+              'label-2': 'Sample 1.2'
             },
             {
-              label: 'Label 2',
-              prop: 'label-2'
+              'label-1': 'Sample 2.1',
+              'label-2': 'Sample 2.2'
             }
           ]
-        };
 
-        scope.data = [
-          {
-            'label-1': 'Sample 1.1',
-            'label-2': 'Sample 1.2'
-          },
-          {
-            'label-1': 'Sample 2.1',
-            'label-2': 'Sample 2.2'
-          }
-        ]
+          element = angular.element('<xos-table config="config" data="data"></xos-table>');
+          $compile(element)(scope);
+          scope.$digest();
+          isolatedScope = element.isolateScope().vm;
+        }));
 
-        element = angular.element('<xos-table config="config" data="data"></xos-table>');
-        $compile(element)(scope);
-        // scope.$apply();
-        element.scope().$apply();
-        isolatedScope = element.isolateScope();
-        console.log(element, isolatedScope);
-      }));
+        it('should contain 2 columns', function() {
+          var th = element[0].getElementsByTagName('th');
+          expect(th.length).toEqual(2);
+          expect(isolatedScope.columns.length).toEqual(2);
+        });
 
-      xit('should contain 2 columns', function() {
-        console.log('aaa', isolatedScope);
-        
-        // one is the filter, the other two are the products, one is the pagination
-        expect(isolatedScope.columns).toEqual(2);
+        it('should contain 3 rows', function() {
+          var tr = element[0].getElementsByTagName('tr');
+          expect(tr.length).toEqual(3);
+        });
+
+        describe('when actions are passed', () => {
+
+          let cb = jasmine.createSpy('callback')
+
+          beforeEach(() => {
+            isolatedScope.config.actions = [
+              {
+                label: 'delete',
+                icon: 'remove',
+                cb: cb,
+                color: 'red'
+              }
+            ];
+            scope.$digest();
+          });
+
+          it('should have 3 columns', () => {
+            var th = element[0].getElementsByTagName('th');
+            expect(th.length).toEqual(3);
+            expect(isolatedScope.columns.length).toEqual(2);
+          });
+
+          it('when clicking on action should invoke callback', () => {
+            var link = element[0].getElementsByTagName('a')[0];
+            link.click();
+            expect(cb).toHaveBeenCalledWith(scope.data[0]);
+          });
+        });
+
+        describe('when filter is fulltext', () => {
+          beforeEach(() => {
+            isolatedScope.config.filter = 'fulltext';
+            scope.$digest();
+          });
+
+          it('should render a text field', () => {
+            var textField = element[0].getElementsByTagName('input');
+            expect(textField.length).toEqual(1);
+          });
+
+          describe('and a value is enterd', () => {
+            beforeEach(() => {
+              isolatedScope.query = '2.2';
+              scope.$digest();
+            });
+
+            it('should contain 2 rows', function() {
+              var tr = element[0].getElementsByTagName('tr');
+              expect(tr.length).toEqual(2);
+            });
+          });
+        });
+
+        describe('when filter is field', () => {
+          beforeEach(() => {
+            isolatedScope.config.filter = 'field';
+            scope.$digest();
+          });
+
+          it('should render a text field for each column', () => {
+            var textField = element[0].getElementsByTagName('input');
+            expect(textField.length).toEqual(2);
+          });
+
+          describe('and a value is enterd', () => {
+            beforeEach(() => {
+              isolatedScope.query = {'label-1': '2.1'};
+              scope.$digest();
+            });
+
+            it('should contain 3 rows', function() {
+              var tr = element[0].getElementsByTagName('tr');
+              expect(tr.length).toEqual(3);
+            });
+          });
+        });
       });
     });
   });
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/table/table.component.js b/views/ngXosLib/xosHelpers/src/ui_components/table/table.component.js
index 4d117ae..f889a3b 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/table/table.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/table/table.component.js
@@ -22,6 +22,29 @@
     * @name xos.uiComponents.table.directive:xosTable
     * @restrict E
     * @description The xos-table directive
+    * @param {Object} config The configuration for the component.
+    * ```
+    * {
+    *   columns: [
+    *     {
+    *       label: 'Human readable name',
+    *       prop: 'Property to read in the model object'
+    *     }
+    *   ],
+    *   classes: 'table table-striped table-bordered',
+    *   actions: [ // if defined add an action column
+          {
+            label: 'delete',
+            icon: 'remove', // refers to bootstraps glyphicon
+            cb: (user) => { // receive the model
+              console.log(user);
+            },
+            color: 'red'
+          }
+        ]
+    * }
+    * ```
+    * @param {Array} data The data that should be rendered
     * @element ANY
     * @scope
     * @example
@@ -30,7 +53,6 @@
     <file name="index.html">
       <div ng-controller="SampleCtrl1 as vm">
         <xos-table data="vm.data" config="vm.config"></xos-table>
-        </xos-table>
       </div>
     </file>
     <file name="script.js">
@@ -39,8 +61,8 @@
         this.config = {
           columns: [
             {
-              label: 'First Name',
-              prop: 'name'
+              label: 'First Name', // column title
+              prop: 'name' // property to read in the data array
             },
             {
               label: 'Last Name',
@@ -63,11 +85,10 @@
     </file>
   </example>
 
-    <example module="sampleModule2">
+  <example module="sampleModule2">
     <file name="index.html">
       <div ng-controller="SampleCtrl2 as vm">
         <xos-table data="vm.data" config="vm.config"></xos-table>
-        </xos-table>
       </div>
     </file>
     <file name="script.js">
@@ -76,23 +97,23 @@
         this.config = {
           columns: [
             {
-              label: 'First Name',
-              prop: 'name'
+              label: 'First Name', // column title
+              prop: 'name' // property to read in the data array
             },
             {
               label: 'Last Name',
               prop: 'lastname'
             }
           ],
-          classes: 'table table-striped table-condensed',
-          actions: [
+          classes: 'table table-striped table-condensed', // table classes, default to `table table-striped table-bordered`
+          actions: [ // if defined add an action column
             {
-              label: 'delete',
-              icon: 'remove',
-              cb: (user) => {
+              label: 'delete', // label
+              icon: 'remove', // icons, refers to bootstraps glyphicon
+              cb: (user) => { // callback, get feeded with the full object
                 console.log(user);
               },
-              color: 'red'
+              color: 'red' // icon color
             }
           ]
         };
@@ -122,6 +143,15 @@
         },
         template: `
           <!-- <pre>{{vm.data | json}}</pre> -->
+          <div class="row" ng-if="vm.config.filter == 'fulltext'">
+            <div class="col-xs-12">
+              <input
+                class="form-control"
+                placeholder="Type to search.."
+                type="text"
+                ng-model="vm.query"/>
+            </div>
+          </div>
           <table ng-class="vm.classes" ng-show="vm.data.length > 0">
             <thead>
               <tr>
@@ -129,15 +159,30 @@
                 <th ng-if="vm.config.actions">Actions</th>
               </tr>
             </thead>
+            <tbody ng-if="vm.config.filter == 'field'">
+              <tr>
+                <td ng-repeat="col in vm.columns">
+                  <input
+                    class="form-control"
+                    placeholder="Type to search by {{col.label}}"
+                    type="text"
+                    ng-model="vm.query[col.prop]"/>
+                </td>
+                <td ng-if="vm.config.actions"></td>
+              </tr>
+            </tbody>
             <tbody>
-              <tr ng-repeat="item in vm.data">
+              <tr ng-repeat="item in vm.data | filter:vm.query">
                 <td ng-repeat="col in vm.columns">{{item[col.prop]}}</td>
                 <td ng-if="vm.config.actions">
-                  <i
+                  <a href=""
                     ng-repeat="action in vm.config.actions"
                     ng-click="action.cb(item)"
-                    class="glyphicon glyphicon-{{action.icon}}"
-                    style="color: {{action.color}};"></i>
+                    title="{{action.label}}">
+                    <i
+                      class="glyphicon glyphicon-{{action.icon}}"
+                      style="color: {{action.color}};"></i>
+                  </a>
                 </td>
               </tr>
             </tbody>