From 810f07c4048cd77190101786b4d1f8b525464bc0 Mon Sep 17 00:00:00 2001
From: Thomas Steur <thomas.steur@googlemail.com>
Date: Wed, 24 Sep 2014 11:11:29 +0200
Subject: [PATCH] refs #5983 started to apply the angular style guide.
 refactored models, use named functions, IIFE

---
 plugins/CoreHome/angularjs/anchorLinkFix.js   |   6 +-
 .../common/directives/autocomplete-matched.js |  44 +-
 .../directives/autocomplete-matched_spec.js   |  71 +--
 .../angularjs/common/directives/dialog.js     |  44 +-
 .../angularjs/common/directives/directive.js  |   5 +-
 .../directives/focus-anywhere-but-here.js     |  46 +-
 .../angularjs/common/directives/focusif.js    |  32 +-
 .../common/directives/ignore-click.js         |  18 +-
 .../angularjs/common/directives/onenter.js    |  28 +-
 .../angularjs/common/directives/translate.js  |  30 +-
 .../angularjs/common/filters/evolution.js     |  57 +-
 .../angularjs/common/filters/filter.js        |   4 +-
 .../angularjs/common/filters/length.js        |  20 +-
 .../angularjs/common/filters/pretty-url.js    |  14 +-
 .../angularjs/common/filters/startfrom.js     |  15 +-
 .../common/filters/startfrom_spec.js          |  43 +-
 .../angularjs/common/filters/translate.js     |  23 +-
 .../CoreHome/angularjs/common/filters/trim.js |  19 +-
 .../angularjs/common/services/piwik-api.js    | 425 ++++++++-------
 .../common/services/piwik-api_spec.js         | 427 +++++++--------
 .../angularjs/common/services/piwik.js        |  13 +-
 .../angularjs/common/services/piwik_spec.js   |  43 +-
 .../angularjs/common/services/service.js      |   5 +-
 .../dialogtoggler/dialogtoggler-controller.js | 100 ++--
 .../dialogtoggler/dialogtoggler-directive.js  |  16 +-
 .../dialogtoggler-urllistener-service.js      | 104 ++--
 .../enrichedheadline-directive.js             |  72 +--
 plugins/CoreHome/angularjs/http404check.js    |  79 +--
 .../menudropdown/menudropdown-directive.js    |  90 ++--
 plugins/CoreHome/angularjs/piwikApp.js        |  25 +-
 plugins/CoreHome/angularjs/piwikAppConfig.js  |   4 +-
 .../siteselector/siteselector-controller.js   |  61 ++-
 .../siteselector/siteselector-directive.js    | 108 ++--
 .../siteselector/siteselector-model.js        | 168 +++---
 .../ratefeature/ratefeature-controller.js     |  29 +-
 .../ratefeature/ratefeature-directive.js      |  24 +-
 .../ratefeature/ratefeature-model.js          |  29 +-
 .../languageselector-directive.js             |  36 +-
 .../translationsearch-controller.js           |  26 +-
 .../translationsearch-directive.js            |  20 +-
 .../dashboard/dashboard-controller.js         |  45 +-
 .../dashboard/dashboard-directive.js          |  40 +-
 .../angularjs/dashboard/dashboard-filter.js   |  62 ++-
 .../angularjs/dashboard/dashboard-model.js    | 509 +++++++++---------
 .../angularjs/site/site-directive.js          |  64 +--
 .../javascripts/sites-manager-controller.js   | 345 ++++++------
 .../javascripts/sites-manager-directives.js   | 119 ++--
 .../javascripts/sites-manager-recipes.js      | 157 +++---
 .../sites-manager-site-controller.js          | 269 ++++-----
 .../quick-access/quick-access-directive.js    | 194 +++----
 .../zen-mode/zen-mode-switcher-directive.js   |  64 +--
 51 files changed, 2253 insertions(+), 2038 deletions(-)

diff --git a/plugins/CoreHome/angularjs/anchorLinkFix.js b/plugins/CoreHome/angularjs/anchorLinkFix.js
index 59d8114a56..ec07049ef7 100644
--- a/plugins/CoreHome/angularjs/anchorLinkFix.js
+++ b/plugins/CoreHome/angularjs/anchorLinkFix.js
@@ -80,7 +80,9 @@
     {
         angular.module('piwikApp').run(['$rootScope', function ($rootScope) {
 
-            $rootScope.$on('$locationChangeStart', function (event, newUrl, oldUrl, $location) {
+            $rootScope.$on('$locationChangeStart', onLocationChangeStart);
+
+            function onLocationChangeStart (event, newUrl, oldUrl, $location) {
 
                 if (!newUrl) {
                     return;
@@ -98,7 +100,7 @@
                 var hash = newUrl.substr(hashPos + 2);
 
                 scrollToAnchorIfPossible(hash, event);
-            });
+            }
         }]);
     }
 
diff --git a/plugins/CoreHome/angularjs/common/directives/autocomplete-matched.js b/plugins/CoreHome/angularjs/common/directives/autocomplete-matched.js
index 0a0c32be0b..5594f4194d 100644
--- a/plugins/CoreHome/angularjs/common/directives/autocomplete-matched.js
+++ b/plugins/CoreHome/angularjs/common/directives/autocomplete-matched.js
@@ -15,28 +15,32 @@
  * <div piwik-autocomplete-matched="searchTerm">{{ name }}</div>
  * <input type="text" ng-model="searchTerm">
  */
-angular.module('piwikApp.directive').directive('piwikAutocompleteMatched', function() {
-    return function(scope, element, attrs) {
-        var searchTerm;
+(function () {
+    angular.module('piwikApp.directive').directive('piwikAutocompleteMatched', piwikAutocompleteMatched);
 
-        scope.$watch(attrs.piwikAutocompleteMatched, function(value) {
-            searchTerm = value;
-            updateText();
-        });
+    function piwikAutocompleteMatched() {
+        return function(scope, element, attrs) {
+            var searchTerm;
 
-        function updateText () {
-            if (!searchTerm || !element) {
-                return;
-            }
+            scope.$watch(attrs.piwikAutocompleteMatched, function(value) {
+                searchTerm = value;
+                updateText();
+            });
+
+            function updateText () {
+                if (!searchTerm || !element) {
+                    return;
+                }
 
-            var content   = element.html();
-            var startTerm = content.toLowerCase().indexOf(searchTerm.toLowerCase());
+                var content   = element.html();
+                var startTerm = content.toLowerCase().indexOf(searchTerm.toLowerCase());
 
-            if (-1 !== startTerm) {
-                var word = content.substr(startTerm, searchTerm.length);
-                content = content.replace(word, '<span class="autocompleteMatched">' + word + '</span>');
-                element.html(content);
+                if (-1 !== startTerm) {
+                    var word = content.substr(startTerm, searchTerm.length);
+                    content = content.replace(word, '<span class="autocompleteMatched">' + word + '</span>');
+                    element.html(content);
+                }
             }
-        }
-    };
-});
\ No newline at end of file
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/directives/autocomplete-matched_spec.js b/plugins/CoreHome/angularjs/common/directives/autocomplete-matched_spec.js
index 0fcc9191db..09ef14b21e 100644
--- a/plugins/CoreHome/angularjs/common/directives/autocomplete-matched_spec.js
+++ b/plugins/CoreHome/angularjs/common/directives/autocomplete-matched_spec.js
@@ -4,40 +4,41 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
-
-describe('piwikAutocompleteMatchedDirective', function() {
-    var $compile;
-    var $rootScope;
-
-    beforeEach(module('piwikApp.directive'));
-    beforeEach(inject(function(_$compile_, _$rootScope_){
-        $compile = _$compile_;
-        $rootScope = _$rootScope_;
-    }));
-
-    function assertRenderedContentIs(query, expectedResult) {
-        var template = '<div piwik-autocomplete-matched="\'' + query + '\'">My Content</div>';
-        var element  = $compile(template)($rootScope);
-        $rootScope.$digest();
-        expect(element.html()).to.eql(expectedResult);
-    }
-
-    describe('#piwikAutocompleteMatched()', function() {
-
-        it('should not change anything if query does not match the text', function() {
-            assertRenderedContentIs('Whatever', 'My Content');
-        });
-
-        it('should wrap the matching part and find case insensitive', function() {
-            assertRenderedContentIs('y cont', 'M<span class="autocompleteMatched">y Cont</span>ent');
-        });
-
-        it('should be able to wrap the whole content', function() {
-            assertRenderedContentIs('my content', '<span class="autocompleteMatched">My Content</span>');
-        });
-
-        it('should find matching content case sensitive', function() {
-            assertRenderedContentIs('My Co', '<span class="autocompleteMatched">My Co</span>ntent');
+(function () {
+    describe('piwikAutocompleteMatchedDirective', function() {
+        var $compile;
+        var $rootScope;
+
+        beforeEach(module('piwikApp.directive'));
+        beforeEach(inject(function(_$compile_, _$rootScope_){
+            $compile = _$compile_;
+            $rootScope = _$rootScope_;
+        }));
+
+        function assertRenderedContentIs(query, expectedResult) {
+            var template = '<div piwik-autocomplete-matched="\'' + query + '\'">My Content</div>';
+            var element  = $compile(template)($rootScope);
+            $rootScope.$digest();
+            expect(element.html()).to.eql(expectedResult);
+        }
+
+        describe('#piwikAutocompleteMatched()', function() {
+
+            it('should not change anything if query does not match the text', function() {
+                assertRenderedContentIs('Whatever', 'My Content');
+            });
+
+            it('should wrap the matching part and find case insensitive', function() {
+                assertRenderedContentIs('y cont', 'M<span class="autocompleteMatched">y Cont</span>ent');
+            });
+
+            it('should be able to wrap the whole content', function() {
+                assertRenderedContentIs('my content', '<span class="autocompleteMatched">My Content</span>');
+            });
+
+            it('should find matching content case sensitive', function() {
+                assertRenderedContentIs('My Co', '<span class="autocompleteMatched">My Co</span>ntent');
+            });
         });
     });
-});
\ No newline at end of file
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/directives/dialog.js b/plugins/CoreHome/angularjs/common/directives/dialog.js
index 71157aeb71..24c1aeb974 100644
--- a/plugins/CoreHome/angularjs/common/directives/dialog.js
+++ b/plugins/CoreHome/angularjs/common/directives/dialog.js
@@ -15,27 +15,31 @@
  * </div>
  * Will execute the "executeMyFunction" function in the current scope once the yes button is pressed.
  */
-angular.module('piwikApp.directive').directive('piwikDialog', function(piwik, $parse) {
+(function () {
+    angular.module('piwikApp.directive').directive('piwikDialog', piwikDialog);
 
-    return {
-        restrict: 'A',
-        link: function(scope, element, attrs) {
+    function piwikDialog(piwik, $parse) {
 
-            element.css('display', 'none');
+        return {
+            restrict: 'A',
+            link: function(scope, element, attrs) {
 
-            element.on( "dialogclose", function() {
-                scope.$apply($parse(attrs.piwikDialog).assign(scope, false));
-            });
+                element.css('display', 'none');
 
-            scope.$watch(attrs.piwikDialog, function(newValue, oldValue) {
-                if (newValue) {
-                    piwik.helper.modalConfirm(element, {yes: function() {
-                        if (attrs.yes) {
-                            scope.$eval(attrs.yes);
-                        }
-                    }});
-                }
-            });
-        }
-    };
-});
\ No newline at end of file
+                element.on( "dialogclose", function() {
+                    scope.$apply($parse(attrs.piwikDialog).assign(scope, false));
+                });
+
+                scope.$watch(attrs.piwikDialog, function(newValue, oldValue) {
+                    if (newValue) {
+                        piwik.helper.modalConfirm(element, {yes: function() {
+                            if (attrs.yes) {
+                                scope.$eval(attrs.yes);
+                            }
+                        }});
+                    }
+                });
+            }
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/directives/directive.js b/plugins/CoreHome/angularjs/common/directives/directive.js
index c2d119e26e..5106f5be14 100644
--- a/plugins/CoreHome/angularjs/common/directives/directive.js
+++ b/plugins/CoreHome/angularjs/common/directives/directive.js
@@ -4,5 +4,6 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
-
-angular.module('piwikApp.directive', []);
+(function () {
+    angular.module('piwikApp.directive', []);
+})();
diff --git a/plugins/CoreHome/angularjs/common/directives/focus-anywhere-but-here.js b/plugins/CoreHome/angularjs/common/directives/focus-anywhere-but-here.js
index f30c765b7d..f7c671f3df 100644
--- a/plugins/CoreHome/angularjs/common/directives/focus-anywhere-but-here.js
+++ b/plugins/CoreHome/angularjs/common/directives/focus-anywhere-but-here.js
@@ -12,29 +12,33 @@
  * Example:
  * <div piwik-focus-anywhere-but-here="closeDialog()">my dialog</div>
  */
-angular.module('piwikApp.directive').directive('piwikFocusAnywhereButHere', function($document){
-    return {
-        restrict: 'A',
-        link: function(scope, element, attr, ctrl) {
+(function () {
+    angular.module('piwikApp.directive').directive('piwikFocusAnywhereButHere', piwikFocusAnywhereButHere);
 
-            function onClickOutsideElement (event) {
-                if (element.has(event.target).length === 0) {
-                    scope.$apply(attr.piwikFocusAnywhereButHere);
+    function piwikFocusAnywhereButHere($document){
+        return {
+            restrict: 'A',
+            link: function(scope, element, attr, ctrl) {
+
+                function onClickOutsideElement (event) {
+                    if (element.has(event.target).length === 0) {
+                        scope.$apply(attr.piwikFocusAnywhereButHere);
+                    }
                 }
-            }
 
-            function onEscapeHandler (event) {
-                if (event.which === 27) {
-                    scope.$apply(attr.piwikFocusAnywhereButHere);
+                function onEscapeHandler (event) {
+                    if (event.which === 27) {
+                        scope.$apply(attr.piwikFocusAnywhereButHere);
+                    }
                 }
-            }
 
-            $document.on('keyup', onEscapeHandler);
-            $document.on('mouseup', onClickOutsideElement);
-            scope.$on('$destroy', function() {
-                $document.off('mouseup', onClickOutsideElement);
-                $document.off('keyup', onEscapeHandler);
-            });
-        }
-    };
-});
+                $document.on('keyup', onEscapeHandler);
+                $document.on('mouseup', onClickOutsideElement);
+                scope.$on('$destroy', function() {
+                    $document.off('mouseup', onClickOutsideElement);
+                    $document.off('keyup', onEscapeHandler);
+                });
+            }
+        };
+    }
+})();
diff --git a/plugins/CoreHome/angularjs/common/directives/focusif.js b/plugins/CoreHome/angularjs/common/directives/focusif.js
index 2565016536..0f58710248 100644
--- a/plugins/CoreHome/angularjs/common/directives/focusif.js
+++ b/plugins/CoreHome/angularjs/common/directives/focusif.js
@@ -11,17 +11,21 @@
  * Example:
  * <input type="text" piwik-focus-if="view.editName">
  */
-angular.module('piwikApp.directive').directive('piwikFocusIf', function($timeout) {
-    return {
-        restrict: 'A',
-        link: function(scope, element, attrs) {
-            scope.$watch(attrs.piwikFocusIf, function(newValue, oldValue) {
-                if (newValue) {
-                    $timeout(function () {
-                        element[0].focus();
-                    }, 5);
-                }
-            });
-        }
-    };
-});
\ No newline at end of file
+(function () {
+    angular.module('piwikApp.directive').directive('piwikFocusIf', piwikFocusIf);
+
+    function piwikFocusIf($timeout) {
+        return {
+            restrict: 'A',
+            link: function(scope, element, attrs) {
+                scope.$watch(attrs.piwikFocusIf, function(newValue, oldValue) {
+                    if (newValue) {
+                        $timeout(function () {
+                            element[0].focus();
+                        }, 5);
+                    }
+                });
+            }
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/directives/ignore-click.js b/plugins/CoreHome/angularjs/common/directives/ignore-click.js
index e43cae45cb..d90518bdce 100644
--- a/plugins/CoreHome/angularjs/common/directives/ignore-click.js
+++ b/plugins/CoreHome/angularjs/common/directives/ignore-click.js
@@ -12,10 +12,14 @@
  * Example
  * <a piwik-ignore-click ng-click="doSomething()" href="/">my link</a>
  */
-angular.module('piwikApp.directive').directive('piwikIgnoreClick', function() {
-    return function(scope, element, attrs) {
-        $(element).click(function(event) {
-            event.preventDefault();
-        });
-    };
-});
\ No newline at end of file
+(function () {
+    angular.module('piwikApp.directive').directive('piwikIgnoreClick', piwikIgnoreClick);
+
+    function piwikIgnoreClick() {
+        return function(scope, element, attrs) {
+            $(element).click(function(event) {
+                event.preventDefault();
+            });
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/directives/onenter.js b/plugins/CoreHome/angularjs/common/directives/onenter.js
index 5dc2daa3a8..d8d39d21b8 100644
--- a/plugins/CoreHome/angularjs/common/directives/onenter.js
+++ b/plugins/CoreHome/angularjs/common/directives/onenter.js
@@ -12,16 +12,20 @@
  * <div piwik-onenter="save()">
  * <div piwik-onenter="showList=false">
  */
-angular.module('piwikApp.directive').directive('piwikOnenter', function() {
-    return function(scope, element, attrs) {
-        element.bind("keydown keypress", function(event) {
-            if(event.which === 13) {
-                scope.$apply(function(){
-                    scope.$eval(attrs.piwikOnenter, {'event': event});
-                });
+(function () {
+    angular.module('piwikApp.directive').directive('piwikOnenter', piwikOnenter);
 
-                event.preventDefault();
-            }
-        });
-    };
-});
\ No newline at end of file
+    function piwikOnenter() {
+        return function(scope, element, attrs) {
+            element.bind("keydown keypress", function(event) {
+                if(event.which === 13) {
+                    scope.$apply(function(){
+                        scope.$eval(attrs.piwikOnenter, {'event': event});
+                    });
+
+                    event.preventDefault();
+                }
+            });
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/directives/translate.js b/plugins/CoreHome/angularjs/common/directives/translate.js
index 17e0638476..4cc20e83b3 100644
--- a/plugins/CoreHome/angularjs/common/directives/translate.js
+++ b/plugins/CoreHome/angularjs/common/directives/translate.js
@@ -17,16 +17,20 @@
  *     first arg::<strong>second arg</strong>::{{ unsafeDataThatWillBeSanitized }}
  * </span>
  */
-angular.module('piwikApp.directive').directive('piwikTranslate', function() {
-    return {
-        restrict: 'A',
-        scope: {
-            piwikTranslate: '@'
-        },
-        compile: function(element, attrs) {
-          var parts = element.html().split('::'),
-                translated = _pk_translate(attrs.piwikTranslate, parts);
-            element.html(translated);
-        }
-    };
-});
+(function () {
+    angular.module('piwikApp.directive').directive('piwikTranslate', piwikTranslate);
+
+    function piwikTranslate() {
+        return {
+            restrict: 'A',
+            scope: {
+                piwikTranslate: '@'
+            },
+            compile: function(element, attrs) {
+                var parts = element.html().split('::'),
+                    translated = _pk_translate(attrs.piwikTranslate, parts);
+                element.html(translated);
+            }
+        };
+    }
+})();
diff --git a/plugins/CoreHome/angularjs/common/filters/evolution.js b/plugins/CoreHome/angularjs/common/filters/evolution.js
index ae9e279f4e..4ff785c5d8 100644
--- a/plugins/CoreHome/angularjs/common/filters/evolution.js
+++ b/plugins/CoreHome/angularjs/common/filters/evolution.js
@@ -4,41 +4,44 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp.filter').filter('evolution', evolution);
 
-angular.module('piwikApp.filter').filter('evolution', function() {
+    function evolution() {
 
-    function calculateEvolution(currentValue, pastValue)
-    {
-        pastValue    = parseInt(pastValue, 10);
-        currentValue = parseInt(currentValue, 10) - pastValue;
+        function calculateEvolution(currentValue, pastValue)
+        {
+            pastValue    = parseInt(pastValue, 10);
+            currentValue = parseInt(currentValue, 10) - pastValue;
 
-        if (currentValue === 0 || isNaN(currentValue)) {
-            evolution = 0;
-        } else if (pastValue === 0 || isNaN(pastValue)) {
-            evolution = 100;
-        } else {
-            evolution = (currentValue / pastValue) * 100;
+            if (currentValue === 0 || isNaN(currentValue)) {
+                evolution = 0;
+            } else if (pastValue === 0 || isNaN(pastValue)) {
+                evolution = 100;
+            } else {
+                evolution = (currentValue / pastValue) * 100;
+            }
+
+            return evolution;
         }
 
-        return evolution;
-    }
+        function formatEvolution(evolution)
+        {
+            evolution = Math.round(evolution);
+
+            if (evolution > 0) {
+                evolution = '+' + evolution;
+            }
 
-    function formatEvolution(evolution)
-    {
-        evolution = Math.round(evolution);
+            evolution += '%';
 
-        if (evolution > 0) {
-            evolution = '+' + evolution;
+            return evolution;
         }
 
-        evolution += '%';
+        return function(currentValue, pastValue) {
+            var evolution = calculateEvolution(currentValue, pastValue);
 
-        return evolution;
+            return formatEvolution(evolution);
+        };
     }
-
-    return function(currentValue, pastValue) {
-        var evolution = calculateEvolution(currentValue, pastValue);
-
-        return formatEvolution(evolution);
-    };
-});
+})();
diff --git a/plugins/CoreHome/angularjs/common/filters/filter.js b/plugins/CoreHome/angularjs/common/filters/filter.js
index 1a79c4008b..cdb39ef78f 100644
--- a/plugins/CoreHome/angularjs/common/filters/filter.js
+++ b/plugins/CoreHome/angularjs/common/filters/filter.js
@@ -4,4 +4,6 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
-angular.module('piwikApp.filter', []);
+(function () {
+    angular.module('piwikApp.filter', []);
+})();
diff --git a/plugins/CoreHome/angularjs/common/filters/length.js b/plugins/CoreHome/angularjs/common/filters/length.js
index b1625aa826..a648347c49 100644
--- a/plugins/CoreHome/angularjs/common/filters/length.js
+++ b/plugins/CoreHome/angularjs/common/filters/length.js
@@ -4,14 +4,18 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp.filter').filter('length', length);
 
-angular.module('piwikApp.filter').filter('length', function() {
+    function length() {
 
-    return function(stringOrArray) {
-        if (stringOrArray && stringOrArray.length) {
-            return stringOrArray.length;
-        }
+        return function(stringOrArray) {
+            if (stringOrArray && stringOrArray.length) {
+                return stringOrArray.length;
+            }
 
-        return 0;
-    };
-});
+            return 0;
+        };
+    }
+
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/filters/pretty-url.js b/plugins/CoreHome/angularjs/common/filters/pretty-url.js
index f46a64bfaf..e3b67c8775 100644
--- a/plugins/CoreHome/angularjs/common/filters/pretty-url.js
+++ b/plugins/CoreHome/angularjs/common/filters/pretty-url.js
@@ -4,9 +4,13 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp.filter').filter('prettyUrl', prettyUrl);
 
-angular.module('piwikApp.filter').filter('prettyUrl', function() {
-    return function(input) {
-        return input.trim().replace('http://', '');
-    };
-});
+    function prettyUrl() {
+        return function(input) {
+            return input.trim().replace('http://', '');
+        };
+    }
+
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/filters/startfrom.js b/plugins/CoreHome/angularjs/common/filters/startfrom.js
index fa548251da..d912e2064f 100644
--- a/plugins/CoreHome/angularjs/common/filters/startfrom.js
+++ b/plugins/CoreHome/angularjs/common/filters/startfrom.js
@@ -4,10 +4,13 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp.filter').filter('startFrom', startFrom);
 
-angular.module('piwikApp.filter').filter('startFrom', function() {
-    return function(input, start) {
-        start = +start; //parse to int
-        return input.slice(start);
-    };
-});
\ No newline at end of file
+    function startFrom() {
+        return function(input, start) {
+            start = +start; //parse to int
+            return input.slice(start);
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/filters/startfrom_spec.js b/plugins/CoreHome/angularjs/common/filters/startfrom_spec.js
index 802dab7f72..e86e48a618 100644
--- a/plugins/CoreHome/angularjs/common/filters/startfrom_spec.js
+++ b/plugins/CoreHome/angularjs/common/filters/startfrom_spec.js
@@ -4,37 +4,38 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    describe('startFromFilter', function() {
+        var startFrom;
 
-describe('startFromFilter', function() {
-    var startFrom;
+        beforeEach(module('piwikApp.filter'));
+        beforeEach(inject(function($injector) {
+            var $filter = $injector.get('$filter');
+            startFrom = $filter('startFrom');
+        }));
 
-    beforeEach(module('piwikApp.filter'));
-    beforeEach(inject(function($injector) {
-        var $filter = $injector.get('$filter');
-        startFrom = $filter('startFrom');
-    }));
+        describe('#startFrom()', function() {
 
-    describe('#startFrom()', function() {
+            it('should return all entries if index is zero', function() {
 
-        it('should return all entries if index is zero', function() {
+                var result = startFrom([1,2,3], 0);
 
-            var result = startFrom([1,2,3], 0);
+                expect(result).to.eql([1,2,3]);
+            });
 
-            expect(result).to.eql([1,2,3]);
-        });
-
-        it('should return only partial entries if filter is higher than zero', function() {
+            it('should return only partial entries if filter is higher than zero', function() {
 
-            var result = startFrom([1,2,3], 2);
+                var result = startFrom([1,2,3], 2);
 
-            expect(result).to.eql([3]);
-        });
+                expect(result).to.eql([3]);
+            });
 
-        it('should return no entries if start is higher than input length', function() {
+            it('should return no entries if start is higher than input length', function() {
 
-            var result = startFrom([1,2,3], 11);
+                var result = startFrom([1,2,3], 11);
 
-            expect(result).to.eql([]);
+                expect(result).to.eql([]);
+            });
         });
     });
-});
\ No newline at end of file
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/filters/translate.js b/plugins/CoreHome/angularjs/common/filters/translate.js
index a23cbc5314..42494f634e 100644
--- a/plugins/CoreHome/angularjs/common/filters/translate.js
+++ b/plugins/CoreHome/angularjs/common/filters/translate.js
@@ -4,16 +4,19 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp.filter').filter('translate', translate);
 
-angular.module('piwikApp.filter').filter('translate', function() {
+    function translate() {
 
-    return function(key, value1, value2, value3) {
-        var values = [];
-        if (arguments && arguments.length > 1) {
-            for (var index = 1; index < arguments.length; index++) {
-                values.push(arguments[index]);
+        return function(key, value1, value2, value3) {
+            var values = [];
+            if (arguments && arguments.length > 1) {
+                for (var index = 1; index < arguments.length; index++) {
+                    values.push(arguments[index]);
+                }
             }
-        }
-        return _pk_translate(key, values);
-    };
-});
\ No newline at end of file
+            return _pk_translate(key, values);
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/filters/trim.js b/plugins/CoreHome/angularjs/common/filters/trim.js
index f0879a0911..d761618eb9 100644
--- a/plugins/CoreHome/angularjs/common/filters/trim.js
+++ b/plugins/CoreHome/angularjs/common/filters/trim.js
@@ -4,14 +4,17 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp.filter').filter('trim', trim);
 
-angular.module('piwikApp.filter').filter('trim', function() {
+    function trim() {
 
-    return function(string) {
-        if (string) {
-            return $.trim('' + string);
-        }
+        return function(string) {
+            if (string) {
+                return $.trim('' + string);
+            }
 
-        return string;
-    };
-});
+            return string;
+        };
+    }
+})();
diff --git a/plugins/CoreHome/angularjs/common/services/piwik-api.js b/plugins/CoreHome/angularjs/common/services/piwik-api.js
index d92bf0436c..7803c59024 100644
--- a/plugins/CoreHome/angularjs/common/services/piwik-api.js
+++ b/plugins/CoreHome/angularjs/common/services/piwik-api.js
@@ -4,265 +4,272 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp.service').factory('piwikApi', piwikApiService);
+
+    function piwikApiService ($http, $q, $rootScope, piwik, $window) {
+
+        var url = 'index.php';
+        var format = 'json';
+        var getParams  = {};
+        var postParams = {};
+        var allRequests = [];
+
+        /**
+         * Adds params to the request.
+         * If params are given more then once, the latest given value is used for the request
+         *
+         * @param {object}  params
+         * @return {void}
+         */
+        function addParams (params) {
+            if (typeof params == 'string') {
+                params = piwik.broadcast.getValuesFromUrl(params);
+            }
 
-angular.module('piwikApp.service').factory('piwikApi', function ($http, $q, $rootScope, piwik, $window) {
-
-    var url = 'index.php';
-    var format = 'json';
-    var getParams  = {};
-    var postParams = {};
-    var allRequests = [];
-
-    var piwikApi = {};
-
-    /**
-     * Adds params to the request.
-     * If params are given more then once, the latest given value is used for the request
-     *
-     * @param {object}  params
-     * @return {void}
-     */
-    function addParams (params) {
-        if (typeof params == 'string') {
-            params = piwik.broadcast.getValuesFromUrl(params);
+            for (var key in params) {
+                getParams[key] = params[key];
+            }
         }
 
-        for (var key in params) {
-            getParams[key] = params[key];
+        function reset () {
+            getParams  = {};
+            postParams = {};
         }
-    }
-
-    function reset () {
-        getParams  = {};
-        postParams = {};
-    }
-
-    function isErrorResponse(response) {
-        return response && response.result == 'error';
-    }
 
-    function createResponseErrorNotification(response, options) {
-        if (response.message) {
-            var UI = require('piwik/UI');
-            var notification = new UI.Notification();
-            notification.show(response.message, {
-                context: 'error',
-                type: 'toast',
-                id: 'ajaxHelper',
-                placeat: options.placeat
-            });
-            notification.scrollToNotification();
+        function isErrorResponse(response) {
+            return response && response.result == 'error';
         }
-    }
 
-    /**
-     * Send the request
-     * @return $promise
-     */
-    function send (options) {
-        if (!options) {
-            options = {};
+        function createResponseErrorNotification(response, options) {
+            if (response.message) {
+                var UI = require('piwik/UI');
+                var notification = new UI.Notification();
+                notification.show(response.message, {
+                    context: 'error',
+                    type: 'toast',
+                    id: 'ajaxHelper',
+                    placeat: options.placeat
+                });
+                notification.scrollToNotification();
+            }
         }
 
-        var deferred = $q.defer(),
-            requestPromise = deferred.promise;
+        /**
+         * Send the request
+         * @return $promise
+         */
+        function send (options) {
+            if (!options) {
+                options = {};
+            }
 
-        var onError = function (message) {
-            deferred.reject(message);
-        };
+            var deferred = $q.defer(),
+                requestPromise = deferred.promise;
 
-        var onSuccess = function (response) {
-            if (isErrorResponse(response)) {
-                onError(response.message || null);
+            var onError = function (message) {
+                deferred.reject(message);
+            };
 
-                createResponseErrorNotification(response, options);
-            } else {
-                deferred.resolve(response);
-            }
-        };
+            var onSuccess = function (response) {
+                if (isErrorResponse(response)) {
+                    onError(response.message || null);
 
-        var headers = {
-            'Content-Type': 'application/x-www-form-urlencoded',
-            // ie 8,9,10 caches ajax requests, prevent this
-            'cache-control': 'no-cache'
-        };
+                    createResponseErrorNotification(response, options);
+                } else {
+                    deferred.resolve(response);
+                }
+            };
 
-        var ajaxCall = {
-            method: 'POST',
-            url: url,
-            responseType: format,
-            params: _mixinDefaultGetParams(getParams),
-            data: $.param(getPostParams(postParams)),
-            timeout: requestPromise,
-            headers: headers
-        };
+            var headers = {
+                'Content-Type': 'application/x-www-form-urlencoded',
+                // ie 8,9,10 caches ajax requests, prevent this
+                'cache-control': 'no-cache'
+            };
 
-        $http(ajaxCall).success(onSuccess).error(onError);
+            var ajaxCall = {
+                method: 'POST',
+                url: url,
+                responseType: format,
+                params: _mixinDefaultGetParams(getParams),
+                data: $.param(getPostParams(postParams)),
+                timeout: requestPromise,
+                headers: headers
+            };
 
-        // we can't modify requestPromise directly and add an abort method since for some reason it gets
-        // removed after then/finally/catch is called.
-        var addAbortMethod = function (to) {
-            return {
-                then: function () {
-                    return addAbortMethod(to.then.apply(to, arguments));
-                },
+            $http(ajaxCall).success(onSuccess).error(onError);
 
-                'finally': function () {
-                    return addAbortMethod(to['finally'].apply(to, arguments));
-                },
+            // we can't modify requestPromise directly and add an abort method since for some reason it gets
+            // removed after then/finally/catch is called.
+            var addAbortMethod = function (to) {
+                return {
+                    then: function () {
+                        return addAbortMethod(to.then.apply(to, arguments));
+                    },
 
-                'catch': function () {
-                    return addAbortMethod(to['catch'].apply(to, arguments));
-                },
+                    'finally': function () {
+                        return addAbortMethod(to['finally'].apply(to, arguments));
+                    },
 
-                abort: function () {
-                    deferred.reject();
-                    return this;
-                }
+                    'catch': function () {
+                        return addAbortMethod(to['catch'].apply(to, arguments));
+                    },
+
+                    abort: function () {
+                        deferred.reject();
+                        return this;
+                    }
+                };
             };
-        };
 
-        var request = addAbortMethod(requestPromise);
+            var request = addAbortMethod(requestPromise);
 
-        allRequests.push(request);
+            allRequests.push(request);
 
-        return request;
-    }
+            return request;
+        }
 
-    /**
-     * Get the parameters to send as POST
-     *
-     * @param {object}   params   parameter object
-     * @return {object}
-     * @private
-     */
-     function getPostParams (params) {
-        params.token_auth = piwik.token_auth;
-        return params;
-    }
+        /**
+         * Get the parameters to send as POST
+         *
+         * @param {object}   params   parameter object
+         * @return {object}
+         * @private
+         */
+        function getPostParams (params) {
+            params.token_auth = piwik.token_auth;
+            return params;
+        }
 
-    /**
-     * Mixin the default parameters to send as GET
-     *
-     * @param {object}   getParamsToMixin   parameter object
-     * @return {object}
-     * @private
-     */
-    function _mixinDefaultGetParams (getParamsToMixin) {
-
-        var defaultParams = {
-            idSite:  piwik.idSite || piwik.broadcast.getValueFromUrl('idSite'),
-            period:  piwik.period || piwik.broadcast.getValueFromUrl('period'),
-            segment: piwik.broadcast.getValueFromHash('segment', $window.location.href.split('#')[1])
-        };
+        /**
+         * Mixin the default parameters to send as GET
+         *
+         * @param {object}   getParamsToMixin   parameter object
+         * @return {object}
+         * @private
+         */
+        function _mixinDefaultGetParams (getParamsToMixin) {
+
+            var defaultParams = {
+                idSite:  piwik.idSite || piwik.broadcast.getValueFromUrl('idSite'),
+                period:  piwik.period || piwik.broadcast.getValueFromUrl('period'),
+                segment: piwik.broadcast.getValueFromHash('segment', $window.location.href.split('#')[1])
+            };
 
-        // never append token_auth to url
-        if (getParamsToMixin.token_auth) {
-            getParamsToMixin.token_auth = null;
-            delete getParamsToMixin.token_auth;
-        }
+            // never append token_auth to url
+            if (getParamsToMixin.token_auth) {
+                getParamsToMixin.token_auth = null;
+                delete getParamsToMixin.token_auth;
+            }
 
-        for (var key in defaultParams) {
-            if (!getParamsToMixin[key] && !postParams[key] && defaultParams[key]) {
-                getParamsToMixin[key] = defaultParams[key];
+            for (var key in defaultParams) {
+                if (!getParamsToMixin[key] && !postParams[key] && defaultParams[key]) {
+                    getParamsToMixin[key] = defaultParams[key];
+                }
             }
-        }
 
-        // handle default date & period if not already set
-        if (!getParamsToMixin.date && !postParams.date) {
-            getParamsToMixin.date = piwik.currentDateString || piwik.broadcast.getValueFromUrl('date');
-            if (getParamsToMixin.period == 'range' && piwik.currentDateString) {
-                getParamsToMixin.date = piwik.startDateString + ',' + getParamsToMixin.date;
+            // handle default date & period if not already set
+            if (!getParamsToMixin.date && !postParams.date) {
+                getParamsToMixin.date = piwik.currentDateString || piwik.broadcast.getValueFromUrl('date');
+                if (getParamsToMixin.period == 'range' && piwik.currentDateString) {
+                    getParamsToMixin.date = piwik.startDateString + ',' + getParamsToMixin.date;
+                }
             }
-        }
 
-        return getParamsToMixin;
-    }
+            return getParamsToMixin;
+        }
 
-    piwikApi.abortAll = function () {
-        reset();
+        function abortAll() {
+            reset();
 
-        allRequests.forEach(function (request) {
-            request.abort();
-        });
+            allRequests.forEach(function (request) {
+                request.abort();
+            });
 
-        allRequests = [];
-    };
+            allRequests = [];
+        };
 
-    /**
-     * @deprecated
-     */
-    piwikApi.abort = function () {
-        this.abortAll();
-    };
+        function abort () {
+            abortAll();
+        };
 
-    /**
-     * Perform a reading API request.
-     * @param getParams
-     */
-    piwikApi.fetch = function (getParams, options) {
+        /**
+         * Perform a reading API request.
+         * @param getParams
+         */
+        function fetch (getParams, options) {
 
-        getParams.module = getParams.module || 'API';
-        getParams.format = 'JSON2';
+            getParams.module = getParams.module || 'API';
+            getParams.format = 'JSON2';
 
-        addParams(getParams, 'GET');
+            addParams(getParams, 'GET');
 
-        var promise = send(options);
+            var promise = send(options);
 
-        reset();
+            reset();
 
-        return promise;
-    };
+            return promise;
+        };
 
-    piwikApi.post = function (getParams, _postParams_, options) {
-        if (_postParams_) {
-            postParams = _postParams_;
-        }
+        function post(getParams, _postParams_, options) {
+            if (_postParams_) {
+                postParams = _postParams_;
+            }
 
-        return this.fetch(getParams, options);
-    };
-
-    /**
-     * Convenience method that will perform a bulk request using Piwik's API.getBulkRequest method.
-     * Bulk requests allow you to execute multiple Piwik requests with one HTTP request.
-     *
-     * @param {object[]} requests
-     * @param {object} options
-     * @return {HttpPromise} a promise that is resolved when the request finishes. The argument passed
-     *                       to the .then(...) callback will be an array with one element per request
-     *                       made.
-     */
-    piwikApi.bulkFetch = function (requests, options) {
-        var bulkApiRequestParams = {
-            urls: requests.map(function (requestObj) { return '?' + $.param(requestObj); })
+            return fetch(getParams, options);
         };
 
-        var deferred = $q.defer(),
-            requestPromise = this.post({method: "API.getBulkRequest"}, bulkApiRequestParams, options).then(function (response) {
-                if (!(response instanceof Array)) {
-                    response = [response];
-                }
+        /**
+         * Convenience method that will perform a bulk request using Piwik's API.getBulkRequest method.
+         * Bulk requests allow you to execute multiple Piwik requests with one HTTP request.
+         *
+         * @param {object[]} requests
+         * @param {object} options
+         * @return {HttpPromise} a promise that is resolved when the request finishes. The argument passed
+         *                       to the .then(...) callback will be an array with one element per request
+         *                       made.
+         */
+        function bulkFetch(requests, options) {
+            var bulkApiRequestParams = {
+                urls: requests.map(function (requestObj) { return '?' + $.param(requestObj); })
+            };
 
-                // check for errors
-                for (var i = 0; i != response.length; ++i) {
-                    var specificResponse = response[i];
+            var deferred = $q.defer(),
+                requestPromise = post({method: "API.getBulkRequest"}, bulkApiRequestParams, options).then(function (response) {
+                    if (!(response instanceof Array)) {
+                        response = [response];
+                    }
 
-                    if (isErrorResponse(specificResponse)) {
-                        deferred.reject(specificResponse.message || null);
+                    // check for errors
+                    for (var i = 0; i != response.length; ++i) {
+                        var specificResponse = response[i];
 
-                        createResponseErrorNotification(specificResponse, options || {});
+                        if (isErrorResponse(specificResponse)) {
+                            deferred.reject(specificResponse.message || null);
 
-                        return;
+                            createResponseErrorNotification(specificResponse, options || {});
+
+                            return;
+                        }
                     }
-                }
 
-                deferred.resolve(response);
-            }).catch(function () {
-                deferred.reject.apply(deferred, arguments);
-            });
+                    deferred.resolve(response);
+                }).catch(function () {
+                    deferred.reject.apply(deferred, arguments);
+                });
 
-        return deferred.promise;
-    };
+            return deferred.promise;
+        };
 
-    return piwikApi;
-});
\ No newline at end of file
+        return {
+            bulkFetch: bulkFetch,
+            post: post,
+            fetch: fetch,
+            /**
+             * @deprecated
+             */
+            abort: abort,
+            abortAll: abortAll,
+        }
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/services/piwik-api_spec.js b/plugins/CoreHome/angularjs/common/services/piwik-api_spec.js
index 6e49c14ed1..9f72af9499 100644
--- a/plugins/CoreHome/angularjs/common/services/piwik-api_spec.js
+++ b/plugins/CoreHome/angularjs/common/services/piwik-api_spec.js
@@ -4,275 +4,276 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    describe('piwikApiClient', function () {
+        var piwikApi,
+            $httpBackend;
+
+        if (!window.piwik) window.piwik = {};
+        if (!window.piwik.UI) window.piwik.UI = {};
+        if (!window.piwik.UI.Notification) {
+            window.piwik.UI.Notification = function () {
+                this.show = function () {};
+                this.scrollToNotification = function () {};
+                return this;
+            };
+        }
 
-describe('piwikApiClient', function () {
-    var piwikApi,
-        $httpBackend;
-
-    if (!window.piwik) window.piwik = {};
-    if (!window.piwik.UI) window.piwik.UI = {};
-    if (!window.piwik.UI.Notification) {
-        window.piwik.UI.Notification = function () {
-            this.show = function () {};
-            this.scrollToNotification = function () {};
-            return this;
-        };
-    }
+        beforeEach(module('piwikApp.service'));
+        beforeEach(inject(function($injector) {
+            piwikApi = $injector.get('piwikApi');
 
-    beforeEach(module('piwikApp.service'));
-    beforeEach(inject(function($injector) {
-        piwikApi = $injector.get('piwikApi');
+            $httpBackend = $injector.get('$httpBackend');
 
-        $httpBackend = $injector.get('$httpBackend');
+            $httpBackend.when('POST', /.*getBulkRequest.*/, /.*errorAction.*/).respond(function (method, url, data, headers) {
+                url = url.replace(/date=[^&]+/, "date=");
 
-        $httpBackend.when('POST', /.*getBulkRequest.*/, /.*errorAction.*/).respond(function (method, url, data, headers) {
-            url = url.replace(/date=[^&]+/, "date=");
+                var errorResponse = {result: 'error', message: "error message"},
+                    successResponse= "Response #2: " + url + " - " + data;
 
-            var errorResponse = {result: 'error', message: "error message"},
-                successResponse= "Response #2: " + url + " - " + data;
+                return [200, [errorResponse, successResponse]];
+            });
 
-            return [200, [errorResponse, successResponse]];
-        });
+            $httpBackend.when('POST', /.*getBulkRequest.*/).respond(function (method, url, data, headers) {
+                url = url.replace(/date=[^&]+/, "date=");
 
-        $httpBackend.when('POST', /.*getBulkRequest.*/).respond(function (method, url, data, headers) {
-            url = url.replace(/date=[^&]+/, "date=");
+                var responses = [
+                    "Response #1: " + url + " - " + data,
+                    "Response #2: " + url + " - " + data
+                ];
 
-            var responses = [
-                "Response #1: " + url + " - " + data,
-                "Response #2: " + url + " - " + data
-            ];
+                return [200, JSON.stringify(responses)];
+            });
 
-            return [200, JSON.stringify(responses)];
-        });
+            $httpBackend.when('POST', /.*/).respond(function (method, url, data, headers) {
+                url = url.replace(/date=[^&]+/, "date=");
+                return [200, "Request url: " + url];
+            });
+        }));
 
-        $httpBackend.when('POST', /.*/).respond(function (method, url, data, headers) {
-            url = url.replace(/date=[^&]+/, "date=");
-            return [200, "Request url: " + url];
-        });
-    }));
+        it("should successfully send a request to Piwik when fetch is called", function (done) {
+            piwikApi.fetch({
+                method: "SomePlugin.action"
+            }).then(function (response) {
+                expect(response).to.equal("Request url: index.php?date=&format=JSON2&idSite=1&method=SomePlugin.action&module=API&period=day");
 
-    it("should successfully send a request to Piwik when fetch is called", function (done) {
-        piwikApi.fetch({
-            method: "SomePlugin.action"
-        }).then(function (response) {
-            expect(response).to.equal("Request url: index.php?date=&format=JSON2&idSite=1&method=SomePlugin.action&module=API&period=day");
+                done();
+            }).catch(function (ex) {
+                done(ex);
+            });
 
-            done();
-        }).catch(function (ex) {
-            done(ex);
+            $httpBackend.flush();
         });
 
-        $httpBackend.flush();
-    });
+        it("should chain multiple then callbacks correctly when a fetch succeeds", function (done) {
+            var firstThenDone = false;
 
-    it("should chain multiple then callbacks correctly when a fetch succeeds", function (done) {
-        var firstThenDone = false;
+            piwikApi.fetch({
+                method: "SomePlugin.action"
+            }).then(function (response) {
+                firstThenDone = true;
 
-        piwikApi.fetch({
-            method: "SomePlugin.action"
-        }).then(function (response) {
-            firstThenDone = true;
+                return "newval";
+            }).then(function (response) {
+                expect(firstThenDone).to.equal(true);
+                expect(response).to.equal("newval");
 
-            return "newval";
-        }).then(function (response) {
-            expect(firstThenDone).to.equal(true);
-            expect(response).to.equal("newval");
+                done();
+            }).catch(function (ex) {
+                done(ex);
+            });
 
-            done();
-        }).catch(function (ex) {
-            done(ex);
+            $httpBackend.flush();
         });
 
-        $httpBackend.flush();
-    });
-
-    it("should not fail when multiple aborts are issued", function (done) {
-        var request = piwikApi.fetch({
-            method: "SomePlugin.action"
-        }).then(function (response) {
-            done(new Error("Aborted request succeeded!"));
-        }).catch(function (ex) {
-            done(ex);
-        });
+        it("should not fail when multiple aborts are issued", function (done) {
+            var request = piwikApi.fetch({
+                method: "SomePlugin.action"
+            }).then(function (response) {
+                done(new Error("Aborted request succeeded!"));
+            }).catch(function (ex) {
+                done(ex);
+            });
 
-        request.abort();
-        request.abort();
+            request.abort();
+            request.abort();
 
-        $httpBackend.flush();
+            $httpBackend.flush();
 
-        request.abort();
-    });
+            request.abort();
+        });
 
-    it("should send multiple requests concurrently when fetch is called more than once", function (done) {
-        var request1Done, request2Done;
+        it("should send multiple requests concurrently when fetch is called more than once", function (done) {
+            var request1Done, request2Done;
 
-        function finishIfBothDone() {
-            if (request1Done && request2Done) {
-                done();
+            function finishIfBothDone() {
+                if (request1Done && request2Done) {
+                    done();
+                }
             }
-        }
 
-        piwikApi.fetch({
-            method: "SomePlugin.action"
-        }).then(function (response) {
-            expect(response).to.equal("Request url: index.php?date=&format=JSON2&idSite=1&method=SomePlugin.action&module=API&period=day");
+            piwikApi.fetch({
+                method: "SomePlugin.action"
+            }).then(function (response) {
+                expect(response).to.equal("Request url: index.php?date=&format=JSON2&idSite=1&method=SomePlugin.action&module=API&period=day");
 
-            request1Done = true;
+                request1Done = true;
 
-            finishIfBothDone();
-        }).catch(function (ex) {
-            done(ex);
-        });
+                finishIfBothDone();
+            }).catch(function (ex) {
+                done(ex);
+            });
 
-        piwikApi.fetch({
-            method: "SomeOtherPlugin.action"
-        }).then(function (response) {
-            expect(response).to.equal("Request url: index.php?date=&format=JSON2&idSite=1&method=SomeOtherPlugin.action&module=API&period=day");
+            piwikApi.fetch({
+                method: "SomeOtherPlugin.action"
+            }).then(function (response) {
+                expect(response).to.equal("Request url: index.php?date=&format=JSON2&idSite=1&method=SomeOtherPlugin.action&module=API&period=day");
 
-            request2Done = true;
+                request2Done = true;
 
-            finishIfBothDone();
-        }).catch(function (ex) {
-            done(ex);
-        });
+                finishIfBothDone();
+            }).catch(function (ex) {
+                done(ex);
+            });
 
-        $httpBackend.flush();
-    });
+            $httpBackend.flush();
+        });
 
-    it("should abort individual requests when abort() is called on a promise", function (done) {
-        var request1Done, request2Done;
+        it("should abort individual requests when abort() is called on a promise", function (done) {
+            var request1Done, request2Done;
 
-        function finishIfBothDone() {
-            if (request1Done && request2Done) {
-                done();
+            function finishIfBothDone() {
+                if (request1Done && request2Done) {
+                    done();
+                }
             }
-        }
 
-        var request = piwikApi.fetch({
-            method: "SomePlugin.waitAction"
-        }).then(function (response) {
-            done(new Error("Aborted request finished!"));
-        }).catch(function (ex) {
-            done(ex);
-        }).finally(function () {
-            request1Done = true;
-            finishIfBothDone();
-        });
-
-        piwikApi.fetch({
-            method: "SomeOtherPlugin.action"
-        }).then(function (response) {
-            expect(response).to.equal("Request url: index.php?date=&format=JSON2&idSite=1&method=SomeOtherPlugin.action&module=API&period=day");
+            var request = piwikApi.fetch({
+                method: "SomePlugin.waitAction"
+            }).then(function (response) {
+                done(new Error("Aborted request finished!"));
+            }).catch(function (ex) {
+                done(ex);
+            }).finally(function () {
+                request1Done = true;
+                finishIfBothDone();
+            });
+
+            piwikApi.fetch({
+                method: "SomeOtherPlugin.action"
+            }).then(function (response) {
+                expect(response).to.equal("Request url: index.php?date=&format=JSON2&idSite=1&method=SomeOtherPlugin.action&module=API&period=day");
 
-            request2Done = true;
+                request2Done = true;
 
-            finishIfBothDone();
-        }).catch(function (ex) {
-            done(ex);
-        });
+                finishIfBothDone();
+            }).catch(function (ex) {
+                done(ex);
+            });
 
-        request.abort();
+            request.abort();
 
-        $httpBackend.flush();
-    });
+            $httpBackend.flush();
+        });
 
-    it("should abort all requests when abortAll() is called on the piwikApi", function (done) {
-        var request1Done, request2Done;
+        it("should abort all requests when abortAll() is called on the piwikApi", function (done) {
+            var request1Done, request2Done;
 
-        function finishIfBothDone() {
-            if (request1Done && request2Done) {
-                done();
+            function finishIfBothDone() {
+                if (request1Done && request2Done) {
+                    done();
+                }
             }
-        }
 
-        piwikApi.fetch({
-            method: "SomePlugin.waitAction"
-        }).then(function (response) {
-            done(new Error("Aborted request finished (request 1)!"));
-        }).catch(function (ex) {
-            done(ex);
-        }).finally(function () {
-            request1Done = true;
-            finishIfBothDone();
+            piwikApi.fetch({
+                method: "SomePlugin.waitAction"
+            }).then(function (response) {
+                done(new Error("Aborted request finished (request 1)!"));
+            }).catch(function (ex) {
+                done(ex);
+            }).finally(function () {
+                request1Done = true;
+                finishIfBothDone();
+            });
+
+            piwikApi.fetch({
+                method: "SomePlugin.waitAction"
+            }).then(function (response) {
+                done(new Error("Aborted request finished (request 2)!"));
+            }).catch(function (ex) {
+                done(ex);
+            }).finally(function () {
+                request2Done = true;
+                finishIfBothDone();
+            });
+
+            piwikApi.abortAll();
+
+            $httpBackend.flush();
         });
 
-        piwikApi.fetch({
-            method: "SomePlugin.waitAction"
-        }).then(function (response) {
-            done(new Error("Aborted request finished (request 2)!"));
-        }).catch(function (ex) {
-            done(ex);
-        }).finally(function () {
-            request2Done = true;
-            finishIfBothDone();
-        });
+        it("should perform a bulk request correctly when bulkFetch is called on the piwikApi", function (done) {
+            piwikApi.bulkFetch([
+                {
+                    method: "SomePlugin.action",
+                    param: "value"
+                },
+                {
+                    method: "SomeOtherPlugin.action"
+                }
+            ]).then(function (response) {
+                var restOfExpected = "index.php?date=&format=JSON2&idSite=1&method=API.getBulkRequest&" +
+                    "module=API&period=day - urls%5B%5D=%3Fmethod%3DSomePlugin.action%26param%3D" +
+                    "value&urls%5B%5D=%3Fmethod%3DSomeOtherPlugin.action&token_auth=100bf5eeeed1468f3f9d93750044d3dd";
+
+                expect(response.length).to.equal(2);
+                expect(response[0]).to.equal("Response #1: " + restOfExpected);
+                expect(response[1]).to.equal("Response #2: " + restOfExpected);
 
-        piwikApi.abortAll();
-
-        $httpBackend.flush();
-    });
+                done();
+            }).catch(function (ex) {
+                done(ex);
+            });
 
-    it("should perform a bulk request correctly when bulkFetch is called on the piwikApi", function (done) {
-        piwikApi.bulkFetch([
-            {
-                method: "SomePlugin.action",
-                param: "value"
-            },
-            {
-                method: "SomeOtherPlugin.action"
-            }
-        ]).then(function (response) {
-            var restOfExpected = "index.php?date=&format=JSON2&idSite=1&method=API.getBulkRequest&" +
-                "module=API&period=day - urls%5B%5D=%3Fmethod%3DSomePlugin.action%26param%3D" +
-                "value&urls%5B%5D=%3Fmethod%3DSomeOtherPlugin.action&token_auth=100bf5eeeed1468f3f9d93750044d3dd";
-
-            expect(response.length).to.equal(2);
-            expect(response[0]).to.equal("Response #1: " + restOfExpected);
-            expect(response[1]).to.equal("Response #2: " + restOfExpected);
-
-            done();
-        }).catch(function (ex) {
-            done(ex);
+            $httpBackend.flush();
         });
 
-        $httpBackend.flush();
-    });
+        it("should correctly handle errors in a bulk request response", function (done) {
+            piwikApi.bulkFetch([
+                {
+                    method: "SomePlugin.errorAction"
+                },
+                {
+                    method: "SomeOtherPlugin.whatever"
+                }
+            ]).then(function (response) {
+                done(new Error("promise resolved after bulkFetch request returned an error (response = " + JSON.stringify(response) + ")"));
+            }).catch(function (error) {
+                expect(error).to.equal("error message");
 
-    it("should correctly handle errors in a bulk request response", function (done) {
-        piwikApi.bulkFetch([
-            {
-                method: "SomePlugin.errorAction"
-            },
-            {
-                method: "SomeOtherPlugin.whatever"
-            }
-        ]).then(function (response) {
-            done(new Error("promise resolved after bulkFetch request returned an error (response = " + JSON.stringify(response) + ")"));
-        }).catch(function (error) {
-            expect(error).to.equal("error message");
+                done();
+            });
 
-            done();
+            $httpBackend.flush();
         });
 
-        $httpBackend.flush();
-    });
+        it("shuld correctly handle errors in a bulk request response, regardless of error location", function (done) {
+            piwikApi.bulkFetch([
+                {
+                    method: "SomeOtherPlugin.whatever"
+                },
+                {
+                    method: "SomePlugin.errorAction"
+                }
+            ]).then(function (response) {
+                done(new Error("promise resolved after bulkFetch request returned an error (response = " + JSON.stringify(response) + ")"));
+            }).catch(function (error) {
+                expect(error).to.equal("error message");
 
-    it("shuld correctly handle errors in a bulk request response, regardless of error location", function (done) {
-        piwikApi.bulkFetch([
-            {
-                method: "SomeOtherPlugin.whatever"
-            },
-            {
-                method: "SomePlugin.errorAction"
-            }
-        ]).then(function (response) {
-            done(new Error("promise resolved after bulkFetch request returned an error (response = " + JSON.stringify(response) + ")"));
-        }).catch(function (error) {
-            expect(error).to.equal("error message");
+                done();
+            });
 
-            done();
+            $httpBackend.flush();
         });
-
-        $httpBackend.flush();
     });
-});
\ No newline at end of file
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/services/piwik.js b/plugins/CoreHome/angularjs/common/services/piwik.js
index 80b904dabf..d0ada0dd4e 100644
--- a/plugins/CoreHome/angularjs/common/services/piwik.js
+++ b/plugins/CoreHome/angularjs/common/services/piwik.js
@@ -4,10 +4,13 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp.service').service('piwik', piwikService);
 
-angular.module('piwikApp.service').service('piwik', function () {
+    function piwikService() {
 
-    piwik.helper    = piwikHelper;
-    piwik.broadcast = broadcast;
-    return piwik;
-});
+        piwik.helper    = piwikHelper;
+        piwik.broadcast = broadcast;
+        return piwik;
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/services/piwik_spec.js b/plugins/CoreHome/angularjs/common/services/piwik_spec.js
index c3eacc80ff..44d7678e32 100644
--- a/plugins/CoreHome/angularjs/common/services/piwik_spec.js
+++ b/plugins/CoreHome/angularjs/common/services/piwik_spec.js
@@ -4,34 +4,35 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    describe('piwikService', function() {
+        var piwikService;
 
-describe('piwikService', function() {
-    var piwikService;
+        beforeEach(module('piwikApp.service'));
+        beforeEach(inject(function($injector) {
+            piwikService = $injector.get('piwik');
+        }));
 
-    beforeEach(module('piwikApp.service'));
-    beforeEach(inject(function($injector) {
-        piwikService = $injector.get('piwik');
-    }));
+        describe('#piwikService', function() {
 
-    describe('#piwikService', function() {
+            it('should be the same as piwik global var', function() {
+                piwik.should.equal(piwikService);
+            });
 
-        it('should be the same as piwik global var', function() {
-            piwik.should.equal(piwikService);
-        });
-
-        it('should mixin broadcast', function() {
-            expect(piwikService.broadcast).to.be.an('object');
-        });
+            it('should mixin broadcast', function() {
+                expect(piwikService.broadcast).to.be.an('object');
+            });
 
-        it('should mixin piwikHelper', function() {
-            expect(piwikService.helper).to.be.an('object');
+            it('should mixin piwikHelper', function() {
+                expect(piwikService.helper).to.be.an('object');
+            });
         });
-    });
 
-    describe('#piwik_url', function() {
+        describe('#piwik_url', function() {
 
-        it('should contain the piwik url', function() {
-            expect(piwikService.piwik_url).to.eql('http://localhost/');
+            it('should contain the piwik url', function() {
+                expect(piwikService.piwik_url).to.eql('http://localhost/');
+            });
         });
     });
-});
\ No newline at end of file
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/common/services/service.js b/plugins/CoreHome/angularjs/common/services/service.js
index 0467b40555..24f41cdfd8 100644
--- a/plugins/CoreHome/angularjs/common/services/service.js
+++ b/plugins/CoreHome/angularjs/common/services/service.js
@@ -4,5 +4,6 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
-
-angular.module('piwikApp.service', []);
+(function () {
+    angular.module('piwikApp.service', []);
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-controller.js b/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-controller.js
index cc68a450cc..ed14f40437 100644
--- a/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-controller.js
+++ b/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-controller.js
@@ -9,54 +9,58 @@
  * Controller for the piwikDialogToggler directive. Adds a couple methods to the
  * scope allowing elements to open and close dialogs.
  */
-angular.module('piwikApp').controller('DialogTogglerController', function ($scope, piwik, ngDialog, piwikDialogtogglerUrllistener) {
-    /**
-     * Open a new dialog window using ngDialog.
-     *
-     * @param {object|string} contentsInfo If an object, it is assumed to be ngDialog open(...) config and is
-     *                                     passed to ngDialog.open unaltered.
-     *                                     If a string that beings with '#', we assume it is an ID of an element
-     *                                     with the dialog contents. (Note: ngDialog doesn't appear to support arbitrary
-     *                                     selectors).
-     *                                     If a string that ends with .html, we assume it is a link to a an angular
-     *                                     template.
-     *                                     Otherwise we assume it is a raw angular
-     * @return {object} Returns the result of ngDialog.open. Can be used to close the dialog or listen for
-     *                  when the dialog is closed.
-     */
-    $scope.open = function (contentsInfo) {
-        var ngDialogInfo;
-        if (typeof(contentsInfo) == 'object') { // is info to pass directly to ngDialog
-            ngDialogInfo = contentsInfo;
-        } else if (contentsInfo.substr(0, 1) == '#') { // is ID of an element
-            ngDialogInfo = {template: contentsInfo.substr(1)};
-        } else if (contentsInfo.substr(-4) == '.html') { // is a link to an .html file
-            ngDialogInfo = {template: contentsInfo};
-        } else { // is a raw HTML string
-            ngDialogInfo = {template: contentsInfo, plain: true};
-        }
+(function () {
+    angular.module('piwikApp').controller('DialogTogglerController', DialogTogglerController);
 
-        return ngDialog.open(ngDialogInfo);
-    };
+    function DialogTogglerController($scope, piwik, ngDialog, piwikDialogtogglerUrllistener) {
+        /**
+         * Open a new dialog window using ngDialog.
+         *
+         * @param {object|string} contentsInfo If an object, it is assumed to be ngDialog open(...) config and is
+         *                                     passed to ngDialog.open unaltered.
+         *                                     If a string that beings with '#', we assume it is an ID of an element
+         *                                     with the dialog contents. (Note: ngDialog doesn't appear to support arbitrary
+         *                                     selectors).
+         *                                     If a string that ends with .html, we assume it is a link to a an angular
+         *                                     template.
+         *                                     Otherwise we assume it is a raw angular
+         * @return {object} Returns the result of ngDialog.open. Can be used to close the dialog or listen for
+         *                  when the dialog is closed.
+         */
+        $scope.open = function (contentsInfo) {
+            var ngDialogInfo;
+            if (typeof(contentsInfo) == 'object') { // is info to pass directly to ngDialog
+                ngDialogInfo = contentsInfo;
+            } else if (contentsInfo.substr(0, 1) == '#') { // is ID of an element
+                ngDialogInfo = {template: contentsInfo.substr(1)};
+            } else if (contentsInfo.substr(-4) == '.html') { // is a link to an .html file
+                ngDialogInfo = {template: contentsInfo};
+            } else { // is a raw HTML string
+                ngDialogInfo = {template: contentsInfo, plain: true};
+            }
 
-    /**
-     * Opens a persisted dialog. Persisted dialogs are dialogs that will be launched on reload
-     * of the current URL. They are accomplished by modifying the URL and adding a 'popover'
-     * query parameter.
-     *
-     * @param {string} directive The denormalized name of an angularjs directive. An element with
-     *                           this directive will be the contents of the dialog.
-     * @param {object} attributes Key value mapping of the HTML attributes to add to the dialog's
-     *                            contents element.
-     */
-    $scope.persist = function (directive, attributes) {
-        piwikDialogtogglerUrllistener.propagatePersistedDialog(directive, attributes);
-    };
+            return ngDialog.open(ngDialogInfo);
+        };
 
-    /**
-     * Closes the currently open dialog window.
-     */
-    $scope.close = function () {
-        ngDialog.close();
-    };
-});
\ No newline at end of file
+        /**
+         * Opens a persisted dialog. Persisted dialogs are dialogs that will be launched on reload
+         * of the current URL. They are accomplished by modifying the URL and adding a 'popover'
+         * query parameter.
+         *
+         * @param {string} directive The denormalized name of an angularjs directive. An element with
+         *                           this directive will be the contents of the dialog.
+         * @param {object} attributes Key value mapping of the HTML attributes to add to the dialog's
+         *                            contents element.
+         */
+        $scope.persist = function (directive, attributes) {
+            piwikDialogtogglerUrllistener.propagatePersistedDialog(directive, attributes);
+        };
+
+        /**
+         * Closes the currently open dialog window.
+         */
+        $scope.close = function () {
+            ngDialog.close();
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-directive.js b/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-directive.js
index 4b7859fe1f..2de7aa0a89 100644
--- a/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-directive.js
+++ b/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-directive.js
@@ -18,9 +18,13 @@
  *     <a href="#" ng-click="close()">Close</a>
  * </div>
  */
-angular.module('piwikApp').directive('piwikDialogtoggler', function () {
-    return {
-        restrict: 'A',
-        controller: 'DialogTogglerController'
-    };
-});
\ No newline at end of file
+(function () {
+    angular.module('piwikApp').directive('piwikDialogtoggler', piwikDialogtoggler);
+
+    function piwikDialogtoggler() {
+        return {
+            restrict: 'A',
+            controller: 'DialogTogglerController'
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-urllistener-service.js b/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-urllistener-service.js
index dc8be42323..f4b98ffe9e 100644
--- a/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-urllistener-service.js
+++ b/plugins/CoreHome/angularjs/dialogtoggler/dialogtoggler-urllistener-service.js
@@ -19,64 +19,68 @@
  * TODO: popover as a query parameter refers less to dialogs and more to any popup window
  *       (ie, not necessarily modal). should replace it w/ 'dialog' or maybe 'modal'.
  */
-angular.module('piwikApp').factory('piwikDialogtogglerUrllistener', function ($rootScope, $location, $injector, $rootElement, ngDialog) {
-    var service = {},
-        dialogQueryParamName = 'popover';
+(function () {
+    angular.module('piwikApp').factory('piwikDialogtogglerUrllistener', piwikDialogtogglerUrllistener);
 
-    function getHtmlFromDialogQueryParam(paramValue) {
-        var info = paramValue.split(':'),
-            directiveName = info.shift(),
-            dialogContent = '';
+    function piwikDialogtogglerUrllistener($rootScope, $location, $injector, $rootElement, ngDialog) {
+        var service = {},
+            dialogQueryParamName = 'popover';
 
-        dialogContent += '<div ' + directiveName;
-        angular.forEach(info, function (argumentAssignment) {
-            var pair = argumentAssignment.split('='),
-                key = pair[0],
-                value = pair[1];
-            dialogContent += ' ' + key + '="' + decodeURIComponent(value) + '"';
-        });
-        dialogContent += '/>';
-
-        return dialogContent;
-    }
+        function getHtmlFromDialogQueryParam(paramValue) {
+            var info = paramValue.split(':'),
+                directiveName = info.shift(),
+                dialogContent = '';
 
-    function directiveExists(directiveAttributeString) {
-        // NOTE: directiveNormalize is not exposed by angularjs and the devs don't seem to want to expose it:
-        //       https://github.com/angular/angular.js/issues/7955
-        //       so logic is duplicated here.
-        var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i,
-            directiveName = angular.element.camelCase(directiveAttributeString.replace(PREFIX_REGEXP, ''));
+            dialogContent += '<div ' + directiveName;
+            angular.forEach(info, function (argumentAssignment) {
+                var pair = argumentAssignment.split('='),
+                    key = pair[0],
+                    value = pair[1];
+                dialogContent += ' ' + key + '="' + decodeURIComponent(value) + '"';
+            });
+            dialogContent += '/>';
 
-        return $injector.has(directiveName + 'Directive');
-    }
+            return dialogContent;
+        }
 
-    service.checkUrlForDialog = function () {
-        var dialogParamValue = $location.search()[dialogQueryParamName];
-        if (dialogParamValue && directiveExists(dialogParamValue)) {
-            var dialog = ngDialog.open({
-                template: getHtmlFromDialogQueryParam(dialogParamValue),
-                plain: true,
-                className: ''
-            });
+        function directiveExists(directiveAttributeString) {
+            // NOTE: directiveNormalize is not exposed by angularjs and the devs don't seem to want to expose it:
+            //       https://github.com/angular/angular.js/issues/7955
+            //       so logic is duplicated here.
+            var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i,
+                directiveName = angular.element.camelCase(directiveAttributeString.replace(PREFIX_REGEXP, ''));
 
-            dialog.closePromise.then(function () {
-                $location.search(dialogQueryParamName, null);
-            });
+            return $injector.has(directiveName + 'Directive');
         }
-    };
 
-    service.propagatePersistedDialog = function (directive, attributes) {
-        var paramValue = directive;
-        angular.forEach(attributes, function (value, name) {
-            paramValue += ':' + name + '=' + encodeURIComponent(value);
-        });
+        service.checkUrlForDialog = function () {
+            var dialogParamValue = $location.search()[dialogQueryParamName];
+            if (dialogParamValue && directiveExists(dialogParamValue)) {
+                var dialog = ngDialog.open({
+                    template: getHtmlFromDialogQueryParam(dialogParamValue),
+                    plain: true,
+                    className: ''
+                });
 
-        $location.search(dialogQueryParamName, paramValue);
-    };
+                dialog.closePromise.then(function () {
+                    $location.search(dialogQueryParamName, null);
+                });
+            }
+        };
+
+        service.propagatePersistedDialog = function (directive, attributes) {
+            var paramValue = directive;
+            angular.forEach(attributes, function (value, name) {
+                paramValue += ':' + name + '=' + encodeURIComponent(value);
+            });
 
-    $rootScope.$on('$locationChangeSuccess', function () {
-        service.checkUrlForDialog();
-    });
+            $location.search(dialogQueryParamName, paramValue);
+        };
 
-    return service;
-});
\ No newline at end of file
+        $rootScope.$on('$locationChangeSuccess', function () {
+            service.checkUrlForDialog();
+        });
+
+        return service;
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline-directive.js b/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline-directive.js
index 83956e51ee..d7309ac1ae 100644
--- a/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline-directive.js
+++ b/plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline-directive.js
@@ -22,45 +22,49 @@
  * </h2>
  * -> shows help icon to display inline help on click. Note: You can combine inlinehelp and help-url
  */
-angular.module('piwikApp').directive('piwikEnrichedHeadline', function($document, piwik, $filter){
-    var defaults = {
-        helpUrl: ''
-    };
+(function () {
+    angular.module('piwikApp').directive('piwikEnrichedHeadline', piwikEnrichedHeadline);
 
-    return {
-        transclude: true,
-        restrict: 'A',
-        scope: {
-            helpUrl: '@',
-            featureName: '@'
-        },
-        templateUrl: 'plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline.html?cb=' + piwik.cacheBuster,
-        compile: function (element, attrs) {
+    function piwikEnrichedHeadline($document, piwik, $filter){
+        var defaults = {
+            helpUrl: ''
+        };
 
-            for (var index in defaults) {
-               if (!attrs[index]) { attrs[index] = defaults[index]; }
-            }
+        return {
+            transclude: true,
+            restrict: 'A',
+            scope: {
+                helpUrl: '@',
+                featureName: '@'
+            },
+            templateUrl: 'plugins/CoreHome/angularjs/enrichedheadline/enrichedheadline.html?cb=' + piwik.cacheBuster,
+            compile: function (element, attrs) {
 
-            return function (scope, element, attrs) {
+                for (var index in defaults) {
+                    if (!attrs[index]) { attrs[index] = defaults[index]; }
+                }
 
-                var helpNode = $('[ng-transclude] .inlineHelp', element);
+                return function (scope, element, attrs) {
 
-                if ((!helpNode || !helpNode.length) && element.next()) {
-                    // hack for reports :(
-                    helpNode = element.next().find('.reportDocumentation');
-                }
+                    var helpNode = $('[ng-transclude] .inlineHelp', element);
 
-                if (helpNode && helpNode.length) {
-                    if ($.trim(helpNode.text())) {
-                        scope.inlineHelp = $.trim(helpNode.html());
+                    if ((!helpNode || !helpNode.length) && element.next()) {
+                        // hack for reports :(
+                        helpNode = element.next().find('.reportDocumentation');
                     }
-                    helpNode.remove();
-                }
 
-                if (!attrs.featureName) {
-                    attrs.featureName = $.trim(element.text());
-                }
-            };
-        }
-    };
-});
\ No newline at end of file
+                    if (helpNode && helpNode.length) {
+                        if ($.trim(helpNode.text())) {
+                            scope.inlineHelp = $.trim(helpNode.html());
+                        }
+                        helpNode.remove();
+                    }
+
+                    if (!attrs.featureName) {
+                        attrs.featureName = $.trim(element.text());
+                    }
+                };
+            }
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/http404check.js b/plugins/CoreHome/angularjs/http404check.js
index 0748fa42c6..e859eb5fd6 100644
--- a/plugins/CoreHome/angularjs/http404check.js
+++ b/plugins/CoreHome/angularjs/http404check.js
@@ -1,44 +1,49 @@
-angular.module('piwikApp').factory('http404CheckInterceptor', function($q) {
+(function () {
+    angular.module('piwikApp').factory('http404CheckInterceptor', http404CheckInterceptor);
 
-    function isClientError(rejection)
-    {
-        if (rejection.status === 500) {
-            return true;
+    function http404CheckInterceptor($q) {
+
+        function isClientError(rejection)
+        {
+            if (rejection.status === 500) {
+                return true;
+            }
+
+            return rejection.status >= 400 && rejection.status < 408;
         }
 
-        return rejection.status >= 400 && rejection.status < 408;
-    }
+        return {
+
+            'responseError': function(rejection) {
+                if (rejection &&
+                    isClientError(rejection) &&
+                    rejection.config &&
+                    rejection.config.url &&
+                    -1 !== rejection.config.url.indexOf('.html') &&
+                    -1 !== rejection.config.url.indexOf('plugins')) {
 
-    return {
-
-        'responseError': function(rejection) {
-            if (rejection &&
-                isClientError(rejection) &&
-                rejection.config &&
-                rejection.config.url &&
-                -1 !== rejection.config.url.indexOf('.html') &&
-                -1 !== rejection.config.url.indexOf('plugins')) {
-
-                var posEndUrl = rejection.config.url.indexOf('.html') + 5;
-                var url       = rejection.config.url.substr(0, posEndUrl);
-
-                var message = 'Please check your server configuration. You may want to whitelist "*.html" files from the "plugins" directory.';
-                message    += ' The HTTP status code is ' + rejection.status + ' for URL "' + url + '"';
-
-                var UI = require('piwik/UI');
-                var notification = new UI.Notification();
-                notification.show(message, {
-                    title: 'Failed to load HTML file:',
-                    context: 'error',
-                    id: 'Network_HtmlFileLoadingError'
-                });
+                    var posEndUrl = rejection.config.url.indexOf('.html') + 5;
+                    var url       = rejection.config.url.substr(0, posEndUrl);
+
+                    var message = 'Please check your server configuration. You may want to whitelist "*.html" files from the "plugins" directory.';
+                    message    += ' The HTTP status code is ' + rejection.status + ' for URL "' + url + '"';
+
+                    var UI = require('piwik/UI');
+                    var notification = new UI.Notification();
+                    notification.show(message, {
+                        title: 'Failed to load HTML file:',
+                        context: 'error',
+                        id: 'Network_HtmlFileLoadingError'
+                    });
+                }
+
+                return $q.reject(rejection);
             }
+        };
+    }
 
-            return $q.reject(rejection);
-        }
-    };
-});
+    angular.module('piwikApp').config(['$httpProvider',function($httpProvider) {
+        $httpProvider.interceptors.push('http404CheckInterceptor');
+    }]);
 
-angular.module('piwikApp').config(['$httpProvider',function($httpProvider) {
-    $httpProvider.interceptors.push('http404CheckInterceptor');
-}]);
+})();
diff --git a/plugins/CoreHome/angularjs/menudropdown/menudropdown-directive.js b/plugins/CoreHome/angularjs/menudropdown/menudropdown-directive.js
index 4d21f7a4e1..162039ca42 100644
--- a/plugins/CoreHome/angularjs/menudropdown/menudropdown-directive.js
+++ b/plugins/CoreHome/angularjs/menudropdown/menudropdown-directive.js
@@ -16,54 +16,58 @@
  *     <a class="item" href="/url"></a>
  * </div>
  */
-angular.module('piwikApp').directive('piwikMenudropdown', function(){
+(function () {
+    angular.module('piwikApp').directive('piwikMenudropdown', piwikMenudropdown);
 
-    return {
-        transclude: true,
-        replace: true,
-        restrict: 'A',
-        scope: {
-            menuTitle: '@',
-            tooltip: '@',
-            showSearch: '=',
-            menuTitleChangeOnClick: '='
-        },
-        templateUrl: 'plugins/CoreHome/angularjs/menudropdown/menudropdown.html?cb=' + piwik.cacheBuster,
-        link: function(scope, element, attrs) {
+    function piwikMenudropdown(){
 
-            element.find('.item').on('click', function () {
-                var $self = angular.element(this);
+        return {
+            transclude: true,
+            replace: true,
+            restrict: 'A',
+            scope: {
+                menuTitle: '@',
+                tooltip: '@',
+                showSearch: '=',
+                menuTitleChangeOnClick: '='
+            },
+            templateUrl: 'plugins/CoreHome/angularjs/menudropdown/menudropdown.html?cb=' + piwik.cacheBuster,
+            link: function(scope, element, attrs) {
 
-                if ($self.hasClass('disabled') || $self.hasClass('separator')) {
-                    return;
-                }
+                element.find('.item').on('click', function () {
+                    var $self = angular.element(this);
 
-                if (scope.menuTitleChangeOnClick !== false) {
-                    scope.menuTitle = $self.text().replace(/[\u0000-\u2666]/g, function(c) {
-                        return '&#'+c.charCodeAt(0)+';';
-                    });
-                }
-                scope.$eval('view.showItems = false');
-                scope.$apply();
+                    if ($self.hasClass('disabled') || $self.hasClass('separator')) {
+                        return;
+                    }
+
+                    if (scope.menuTitleChangeOnClick !== false) {
+                        scope.menuTitle = $self.text().replace(/[\u0000-\u2666]/g, function(c) {
+                            return '&#'+c.charCodeAt(0)+';';
+                        });
+                    }
+                    scope.$eval('view.showItems = false');
+                    scope.$apply();
 
-                element.find('.item').removeClass('active');
-                $self.addClass('active');
-            });
+                    element.find('.item').removeClass('active');
+                    $self.addClass('active');
+                });
 
-            scope.searchItems = function (searchTerm)
-            {
-                searchTerm = searchTerm.toLowerCase();
+                scope.searchItems = function (searchTerm)
+                {
+                    searchTerm = searchTerm.toLowerCase();
 
-                element.find('.item').each(function (index, node) {
-                    var $node = angular.element(node);
+                    element.find('.item').each(function (index, node) {
+                        var $node = angular.element(node);
 
-                    if (-1 === $node.text().toLowerCase().indexOf(searchTerm)) {
-                        $node.hide();
-                    } else {
-                        $node.show();
-                    }
-                });
-            };
-        }
-    };
-});
+                        if (-1 === $node.text().toLowerCase().indexOf(searchTerm)) {
+                            $node.hide();
+                        } else {
+                            $node.show();
+                        }
+                    });
+                };
+            }
+        };
+    }
+})();
diff --git a/plugins/CoreHome/angularjs/piwikApp.js b/plugins/CoreHome/angularjs/piwikApp.js
index 3aafe9b87c..d505e34817 100644
--- a/plugins/CoreHome/angularjs/piwikApp.js
+++ b/plugins/CoreHome/angularjs/piwikApp.js
@@ -4,15 +4,16 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
-
-angular.module('piwikApp', [
-    'ngSanitize',
-    'ngAnimate',
-    'ngCookies',
-    'ngDialog',
-    'piwikApp.config',
-    'piwikApp.service',
-    'piwikApp.directive',
-    'piwikApp.filter'
-]);
-angular.module('app', []);
\ No newline at end of file
+(function () {
+    angular.module('piwikApp', [
+        'ngSanitize',
+        'ngAnimate',
+        'ngCookies',
+        'ngDialog',
+        'piwikApp.config',
+        'piwikApp.service',
+        'piwikApp.directive',
+        'piwikApp.filter'
+    ]);
+    angular.module('app', []);
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/piwikAppConfig.js b/plugins/CoreHome/angularjs/piwikAppConfig.js
index 4053dfe54b..8d73dda383 100644
--- a/plugins/CoreHome/angularjs/piwikAppConfig.js
+++ b/plugins/CoreHome/angularjs/piwikAppConfig.js
@@ -1,6 +1,6 @@
-angular.module('piwikApp.config', []);
-
 (function () {
+    angular.module('piwikApp.config', []);
+
     if ('undefined' === (typeof piwik) || !piwik) {
         return;
     }
diff --git a/plugins/CoreHome/angularjs/siteselector/siteselector-controller.js b/plugins/CoreHome/angularjs/siteselector/siteselector-controller.js
index 143a83e402..7f105afccd 100644
--- a/plugins/CoreHome/angularjs/siteselector/siteselector-controller.js
+++ b/plugins/CoreHome/angularjs/siteselector/siteselector-controller.js
@@ -4,43 +4,46 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp').controller('SiteSelectorController', SiteSelectorController);
 
-angular.module('piwikApp').controller('SiteSelectorController', function($scope, siteSelectorModel, piwik, AUTOCOMPLETE_MIN_SITES){
+    function SiteSelectorController($scope, siteSelectorModel, piwik, AUTOCOMPLETE_MIN_SITES){
 
-    $scope.model = siteSelectorModel;
+        $scope.model = siteSelectorModel;
 
-    $scope.autocompleteMinSites = AUTOCOMPLETE_MIN_SITES;
-    $scope.selectedSite = {id: '', name: ''};
-    $scope.activeSiteId = piwik.idSite;
-    $scope.selectedSiteNameHtml = '';
+        $scope.autocompleteMinSites = AUTOCOMPLETE_MIN_SITES;
+        $scope.selectedSite = {id: '', name: ''};
+        $scope.activeSiteId = piwik.idSite;
+        $scope.selectedSiteNameHtml = '';
 
-    $scope.switchSite = function (site) {
-        $scope.selectedSite = {id: site.idsite, name: site.name};
+        $scope.switchSite = function (site) {
+            $scope.selectedSite = {id: site.idsite, name: site.name};
 
-        if (!$scope.switchSiteOnSelect || $scope.activeSiteId == site.idsite) {
-            return;
-        }
+            if (!$scope.switchSiteOnSelect || $scope.activeSiteId == site.idsite) {
+                return;
+            }
 
-        $scope.model.loadSite(site.idsite);
-    };
+            $scope.model.loadSite(site.idsite);
+        };
 
-    $scope.getUrlAllSites = function () {
-        var newParameters = 'module=MultiSites&action=index';
-        return piwik.helper.getCurrentQueryStringWithParametersModified(newParameters);
-    };
-    $scope.getUrlForSiteId = function (idSite) {
-        var idSiteParam   = 'idSite=' + idSite;
-        var newParameters = 'segment=&' + idSiteParam;
-        var hash = piwik.broadcast.isHashExists() ? piwik.broadcast.getHashFromUrl() : "";
-        return piwik.helper.getCurrentQueryStringWithParametersModified(newParameters) +
+        $scope.getUrlAllSites = function () {
+            var newParameters = 'module=MultiSites&action=index';
+            return piwik.helper.getCurrentQueryStringWithParametersModified(newParameters);
+        };
+        $scope.getUrlForSiteId = function (idSite) {
+            var idSiteParam   = 'idSite=' + idSite;
+            var newParameters = 'segment=&' + idSiteParam;
+            var hash = piwik.broadcast.isHashExists() ? piwik.broadcast.getHashFromUrl() : "";
+            return piwik.helper.getCurrentQueryStringWithParametersModified(newParameters) +
             '#' + piwik.helper.getQueryStringWithParametersModified(hash.substring(1), newParameters);
-    };
+        };
 
-    $scope.$watch('selectedSite', function (site) {
-        $scope.selectedSiteNameHtml = site.name.replace(/[\u0000-\u2666]/g, function(c) {
-            return '&#'+c.charCodeAt(0)+';';
+        $scope.$watch('selectedSite', function (site) {
+            $scope.selectedSiteNameHtml = site.name.replace(/[\u0000-\u2666]/g, function(c) {
+                return '&#'+c.charCodeAt(0)+';';
+            });
         });
-    });
 
-    siteSelectorModel.loadInitialSites();
-});
+        siteSelectorModel.loadInitialSites();
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/siteselector/siteselector-directive.js b/plugins/CoreHome/angularjs/siteselector/siteselector-directive.js
index 38107ca635..9d1d8c3092 100644
--- a/plugins/CoreHome/angularjs/siteselector/siteselector-directive.js
+++ b/plugins/CoreHome/angularjs/siteselector/siteselector-directive.js
@@ -23,64 +23,68 @@
  * <div piwik-siteselector id="mySelector">
  * $('#mySelector').on('change', function (event) { event.id/event.name })
  */
-angular.module('piwikApp').directive('piwikSiteselector', function($document, piwik, $filter){
-    var defaults = {
-        name: '',
-        siteid: piwik.idSite,
-        sitename: piwik.siteName,
-        allSitesLocation: 'bottom',
-        allSitesText: $filter('translate')('General_MultiSitesSummary'),
-        showSelectedSite: 'false',
-        showAllSitesItem: 'true',
-        switchSiteOnSelect: 'true'
-    };
+(function () {
+    angular.module('piwikApp').directive('piwikSiteselector', piwikSiteselector);
 
-    return {
-        restrict: 'A',
-        scope: {
-            showSelectedSite: '=',
-            showAllSitesItem: '=',
-            switchSiteOnSelect: '=',
-            inputName: '@name',
-            allSitesText: '@',
-            allSitesLocation: '@'
-        },
-        require: "?ngModel",
-        templateUrl: 'plugins/CoreHome/angularjs/siteselector/siteselector.html?cb=' + piwik.cacheBuster,
-        controller: 'SiteSelectorController',
-        compile: function (element, attrs) {
+    function piwikSiteselector($document, piwik, $filter){
+        var defaults = {
+            name: '',
+            siteid: piwik.idSite,
+            sitename: piwik.siteName,
+            allSitesLocation: 'bottom',
+            allSitesText: $filter('translate')('General_MultiSitesSummary'),
+            showSelectedSite: 'false',
+            showAllSitesItem: 'true',
+            switchSiteOnSelect: 'true'
+        };
 
-            for (var index in defaults) {
-               if (attrs[index] === undefined) {
-                   attrs[index] = defaults[index];
-               }
-            }
-
-            return function (scope, element, attrs, ngModel) {
-                scope.selectedSite = {id: attrs.siteid, name: attrs.sitename};
-                scope.model.loadInitialSites();
+        return {
+            restrict: 'A',
+            scope: {
+                showSelectedSite: '=',
+                showAllSitesItem: '=',
+                switchSiteOnSelect: '=',
+                inputName: '@name',
+                allSitesText: '@',
+                allSitesLocation: '@'
+            },
+            require: "?ngModel",
+            templateUrl: 'plugins/CoreHome/angularjs/siteselector/siteselector.html?cb=' + piwik.cacheBuster,
+            controller: 'SiteSelectorController',
+            compile: function (element, attrs) {
 
-                if (ngModel) {
-                    ngModel.$setViewValue(scope.selectedSite);
+                for (var index in defaults) {
+                    if (attrs[index] === undefined) {
+                        attrs[index] = defaults[index];
+                    }
                 }
 
-                scope.$watch('selectedSite.id', function (newValue, oldValue, scope) {
-                    if (newValue != oldValue) {
-                        element.attr('siteid', newValue);
-                        element.trigger('change', scope.selectedSite);
-                    }
-                });
+                return function (scope, element, attrs, ngModel) {
+                    scope.selectedSite = {id: attrs.siteid, name: attrs.sitename};
+                    scope.model.loadInitialSites();
 
-                scope.$watch('selectedSite', function (newValue) {
                     if (ngModel) {
-                        ngModel.$setViewValue(newValue);
+                        ngModel.$setViewValue(scope.selectedSite);
                     }
-                });
 
-                scope.$watch('view.showSitesList', function (newValue) {
-                    element.toggleClass('expanded', !! newValue);
-                });
-            };
-        }
-    };
-});
\ No newline at end of file
+                    scope.$watch('selectedSite.id', function (newValue, oldValue, scope) {
+                        if (newValue != oldValue) {
+                            element.attr('siteid', newValue);
+                            element.trigger('change', scope.selectedSite);
+                        }
+                    });
+
+                    scope.$watch('selectedSite', function (newValue) {
+                        if (ngModel) {
+                            ngModel.$setViewValue(newValue);
+                        }
+                    });
+
+                    scope.$watch('view.showSitesList', function (newValue) {
+                        element.toggleClass('expanded', !! newValue);
+                    });
+                };
+            }
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/CoreHome/angularjs/siteselector/siteselector-model.js b/plugins/CoreHome/angularjs/siteselector/siteselector-model.js
index 664eaf4ac8..0382303298 100644
--- a/plugins/CoreHome/angularjs/siteselector/siteselector-model.js
+++ b/plugins/CoreHome/angularjs/siteselector/siteselector-model.js
@@ -4,83 +4,91 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
-
-angular.module('piwikApp').factory('siteSelectorModel', function (piwikApi, $filter, piwik) {
-
-    var model = {};
-    model.sites = [];
-    model.hasMultipleWebsites = false;
-    model.isLoading = false;
-    model.firstSiteName = '';
-
-    var initialSites = null;
-
-    model.updateWebsitesList = function (sites) {
-
-        if (!sites || !sites.length) {
-            model.sites = [];
-            return [];
-        }
-
-        angular.forEach(sites, function (site) {
-            if (site.group) site.name = '[' + site.group + '] ' + site.name;
-        });
-
-        model.sites = $filter('orderBy')(sites, '+name');
-
-        if (!model.firstSiteName) {
-            model.firstSiteName = model.sites[0].name;
-        }
-
-        model.hasMultipleWebsites = model.hasMultipleWebsites || sites.length > 1;
-
-        return model.sites;
-    };
-
-    model.searchSite = function (term) {
-
-        if (!term) {
-            model.loadInitialSites();
-            return;
-        }
-
-        if (model.isLoading) {
-            model.currentRequest.abort();
-        }
-
-        model.isLoading = true;
-
-        model.currentRequest = piwikApi.fetch({
-            method: 'SitesManager.getPatternMatchSites',
-            pattern: term
-        }).then(function (response) {
-            return model.updateWebsitesList(response);
-        })['finally'](function () {    // .finally() is not IE8 compatible see https://github.com/angular/angular.js/commit/f078762d48d0d5d9796dcdf2cb0241198677582c
-            model.isLoading = false;
-            model.currentRequest = null;
-        });
-
-        return model.currentRequest;
-    };
-
-    model.loadSite = function (idsite) {
-        if (idsite == 'all') {
-            piwik.broadcast.propagateNewPage('module=MultiSites&action=index');
-        } else {
-            piwik.broadcast.propagateNewPage('segment=&idSite=' + idsite, false);
-        }
-    };
-
-    model.loadInitialSites = function () {
-        if (initialSites) {
-            model.sites = initialSites;
-            return;
-        }
-
-        this.searchSite('%').then(function (websites) {
-            initialSites = websites;
-        });
-    };
-
-    return model;
-});
+(function () {
+    angular.module('piwikApp').factory('siteSelectorModel', siteSelectorModel);
+
+    function siteSelectorModel(piwikApi, $filter, piwik) {
+
+        var initialSites = null;
+
+        var model = {
+            sites : [],
+            hasMultipleWebsites : false,
+            isLoading : false,
+            firstSiteName : '',
+            updateWebsitesList: updateWebsitesList,
+            searchSite: searchSite,
+            loadSite: loadSite,
+            loadInitialSites: loadInitialSites
+        };
+
+        return model;
+
+        function updateWebsitesList(sites) {
+
+            if (!sites || !sites.length) {
+                model.sites = [];
+                return [];
+            }
+
+            angular.forEach(sites, function (site) {
+                if (site.group) site.name = '[' + site.group + '] ' + site.name;
+            });
+
+            model.sites = $filter('orderBy')(sites, '+name');
+
+            if (!model.firstSiteName) {
+                model.firstSiteName = model.sites[0].name;
+            }
+
+            model.hasMultipleWebsites = model.hasMultipleWebsites || sites.length > 1;
+
+            return model.sites;
+        };
+
+        function searchSite(term) {
+
+            if (!term) {
+                loadInitialSites();
+                return;
+            }
+
+            if (model.isLoading) {
+                model.currentRequest.abort();
+            }
+
+            model.isLoading = true;
+
+            model.currentRequest = piwikApi.fetch({
+                method: 'SitesManager.getPatternMatchSites',
+                pattern: term
+            }).then(function (response) {
+                return updateWebsitesList(response);
+            })['finally'](function () {    // .finally() is not IE8 compatible see https://github.com/angular/angular.js/commit/f078762d48d0d5d9796dcdf2cb0241198677582c
+                model.isLoading = false;
+                model.currentRequest = null;
+            });
+
+            return model.currentRequest;
+        };
+
+        function loadSite(idsite) {
+            if (idsite == 'all') {
+                piwik.broadcast.propagateNewPage('module=MultiSites&action=index');
+            } else {
+                piwik.broadcast.propagateNewPage('segment=&idSite=' + idsite, false);
+            }
+        };
+
+        function loadInitialSites() {
+            if (initialSites) {
+                model.sites = initialSites;
+                return;
+            }
+
+            searchSite('%').then(function (websites) {
+                initialSites = websites;
+            });
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature-controller.js b/plugins/Feedback/angularjs/ratefeature/ratefeature-controller.js
index b4dbd1a70a..36a1e8c146 100644
--- a/plugins/Feedback/angularjs/ratefeature/ratefeature-controller.js
+++ b/plugins/Feedback/angularjs/ratefeature/ratefeature-controller.js
@@ -4,20 +4,23 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp').controller('RateFeatureController', RateFeatureController);
 
-angular.module('piwikApp').controller('RateFeatureController', function($scope, rateFeatureModel, $filter){
+    function RateFeatureController($scope, rateFeatureModel, $filter){
 
-    $scope.dislikeFeature = function () {
-        $scope.like = false;
-    };
+        $scope.dislikeFeature = function () {
+            $scope.like = false;
+        };
 
-    $scope.likeFeature = function () {
-        $scope.like = true;
-    };
+        $scope.likeFeature = function () {
+            $scope.like = true;
+        };
 
-    $scope.sendFeedback = function (message) {
-        rateFeatureModel.sendFeedbackForFeature($scope.title, $scope.like, message);
-        $scope.ratingDone = true;
-        // alert($filter('translate')('Feedback_ThankYou'));
-    };
-});
+        $scope.sendFeedback = function (message) {
+            rateFeatureModel.sendFeedbackForFeature($scope.title, $scope.like, message);
+            $scope.ratingDone = true;
+            // alert($filter('translate')('Feedback_ThankYou'));
+        };
+    }
+})();
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature-directive.js b/plugins/Feedback/angularjs/ratefeature/ratefeature-directive.js
index c5f4c32a58..0b92956f84 100644
--- a/plugins/Feedback/angularjs/ratefeature/ratefeature-directive.js
+++ b/plugins/Feedback/angularjs/ratefeature/ratefeature-directive.js
@@ -9,14 +9,18 @@
  * Usage:
  * <div piwik-rate-feature title="My Feature Name">
  */
-angular.module('piwikApp').directive('piwikRateFeature', function($document, piwik, $filter){
+(function () {
+    angular.module('piwikApp').directive('piwikRateFeature', piwikRateFeature);
 
-    return {
-        restrict: 'A',
-        scope: {
-            title: '@'
-        },
-        templateUrl: 'plugins/Feedback/angularjs/ratefeature/ratefeature.html?cb=' + piwik.cacheBuster,
-        controller: 'RateFeatureController'
-    };
-});
\ No newline at end of file
+    function piwikRateFeature($document, piwik, $filter){
+
+        return {
+            restrict: 'A',
+            scope: {
+                title: '@'
+            },
+            templateUrl: 'plugins/Feedback/angularjs/ratefeature/ratefeature.html?cb=' + piwik.cacheBuster,
+            controller: 'RateFeatureController'
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/Feedback/angularjs/ratefeature/ratefeature-model.js b/plugins/Feedback/angularjs/ratefeature/ratefeature-model.js
index b2c9f9009c..934a437e10 100644
--- a/plugins/Feedback/angularjs/ratefeature/ratefeature-model.js
+++ b/plugins/Feedback/angularjs/ratefeature/ratefeature-model.js
@@ -5,18 +5,23 @@
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
 
-angular.module('piwikApp').factory('rateFeatureModel', function (piwikApi) {
+(function () {
+    angular.module('piwikApp').factory('rateFeatureModel', rateFeatureModel);
 
-    var model = {};
+    function rateFeatureModel(piwikApi) {
 
-    model.sendFeedbackForFeature = function (featureName, like, message) {
-        return piwikApi.fetch({
-            method: 'Feedback.sendFeedbackForFeature',
-            featureName: featureName,
-            like: like ? '1' : '0',
-            message: message + ''
-        });
-    };
+        return {
+            sendFeedbackForFeature: sendFeedbackForFeature
+        };
 
-    return model;
-});
+        function sendFeedbackForFeature (featureName, like, message) {
+            return piwikApi.fetch({
+                method: 'Feedback.sendFeedbackForFeature',
+                featureName: featureName,
+                like: like ? '1' : '0',
+                message: message + ''
+            });
+        };
+
+    }
+})();
diff --git a/plugins/LanguagesManager/angularjs/languageselector/languageselector-directive.js b/plugins/LanguagesManager/angularjs/languageselector/languageselector-directive.js
index f50298330e..2dec8b2407 100644
--- a/plugins/LanguagesManager/angularjs/languageselector/languageselector-directive.js
+++ b/plugins/LanguagesManager/angularjs/languageselector/languageselector-directive.js
@@ -10,23 +10,27 @@
  * <div class="languageSelection">
  * </div>
  */
-angular.module('piwikApp').directive('languageSelection', function() {
+(function () {
+    angular.module('piwikApp').directive('languageSelection', languageSelection);
 
-    return {
-        restrict: 'C',
-        link: function(scope, element, attr, ctrl) {
+    function languageSelection() {
 
-            function postLanguageChange () {
-                var value = $(this).attr('value');
-                if (value) {
-                    element.find('#language').val(value).parents('form').submit();
+        return {
+            restrict: 'C',
+            link: function(scope, element, attr, ctrl) {
+
+                function postLanguageChange () {
+                    var value = $(this).attr('value');
+                    if (value) {
+                        element.find('#language').val(value).parents('form').submit();
+                    }
                 }
-            }
 
-            element.on('click', 'a[value]', postLanguageChange);
-            scope.$on('$destroy', function() {
-                element.off('click', 'a[value]', postLanguageChange);
-            });
-        }
-    };
-});
\ No newline at end of file
+                element.on('click', 'a[value]', postLanguageChange);
+                scope.$on('$destroy', function() {
+                    element.off('click', 'a[value]', postLanguageChange);
+                });
+            }
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/LanguagesManager/angularjs/translationsearch/translationsearch-controller.js b/plugins/LanguagesManager/angularjs/translationsearch/translationsearch-controller.js
index ea9dbc0650..2ea3402d49 100644
--- a/plugins/LanguagesManager/angularjs/translationsearch/translationsearch-controller.js
+++ b/plugins/LanguagesManager/angularjs/translationsearch/translationsearch-controller.js
@@ -4,18 +4,20 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp').controller('TranslationSearchController', TranslationSearchController);
 
-angular.module('piwikApp').controller('TranslationSearchController', function($scope, piwikApi) {
+    function TranslationSearchController($scope, piwikApi) {
 
-    $scope.existingTranslations = [];
+        $scope.existingTranslations = [];
 
-    piwikApi.fetch({
-        method: 'LanguagesManager.getTranslationsForLanguage',
-        languageCode: 'en'
-    }).then(function (response) {
-        if (response) {
-            $scope.existingTranslations = response;
-        }
-    });
-
-});
+        piwikApi.fetch({
+            method: 'LanguagesManager.getTranslationsForLanguage',
+            languageCode: 'en'
+        }).then(function (response) {
+            if (response) {
+                $scope.existingTranslations = response;
+            }
+        });
+    }
+})();
\ No newline at end of file
diff --git a/plugins/LanguagesManager/angularjs/translationsearch/translationsearch-directive.js b/plugins/LanguagesManager/angularjs/translationsearch/translationsearch-directive.js
index 7485ab52ca..be0c557a15 100644
--- a/plugins/LanguagesManager/angularjs/translationsearch/translationsearch-directive.js
+++ b/plugins/LanguagesManager/angularjs/translationsearch/translationsearch-directive.js
@@ -13,12 +13,16 @@
  * Will show a text box which allows the user to search for translation keys and actual translations. Currently,
  * only english is supported.
  */
-angular.module('piwikApp').directive('piwikTranslationSearch', function($document, piwik, $filter){
+(function () {
+    angular.module('piwikApp').directive('piwikTranslationSearch', piwikTranslationSearch);
 
-    return {
-        restrict: 'A',
-        scope: {},
-        templateUrl: 'plugins/LanguagesManager/angularjs/translationsearch/translationsearch.html?cb=' + piwik.cacheBuster,
-        controller: 'TranslationSearchController'
-    };
-});
\ No newline at end of file
+    function piwikTranslationSearch($document, piwik, $filter){
+
+        return {
+            restrict: 'A',
+            scope: {},
+            templateUrl: 'plugins/LanguagesManager/angularjs/translationsearch/translationsearch.html?cb=' + piwik.cacheBuster,
+            controller: 'TranslationSearchController'
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/MultiSites/angularjs/dashboard/dashboard-controller.js b/plugins/MultiSites/angularjs/dashboard/dashboard-controller.js
index e38abbbdfc..69102d6a92 100644
--- a/plugins/MultiSites/angularjs/dashboard/dashboard-controller.js
+++ b/plugins/MultiSites/angularjs/dashboard/dashboard-controller.js
@@ -4,31 +4,34 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp').controller('MultiSitesDashboardController', MultiSitesDashboardController);
 
-angular.module('piwikApp').controller('MultiSitesDashboardController', function($scope, piwik, multisitesDashboardModel){
+    function MultiSitesDashboardController($scope, piwik, multisitesDashboardModel){
 
-    $scope.model = multisitesDashboardModel;
+        $scope.model = multisitesDashboardModel;
 
-    $scope.reverse = true;
-    $scope.predicate = 'nb_visits';
-    $scope.evolutionSelector = 'visits_evolution';
-    $scope.hasSuperUserAccess = piwik.hasSuperUserAccess;
-    $scope.date = piwik.broadcast.getValueFromUrl('date');
-    $scope.url  = piwik.piwik_url;
-    $scope.period = piwik.period;
+        $scope.reverse = true;
+        $scope.predicate = 'nb_visits';
+        $scope.evolutionSelector = 'visits_evolution';
+        $scope.hasSuperUserAccess = piwik.hasSuperUserAccess;
+        $scope.date = piwik.broadcast.getValueFromUrl('date');
+        $scope.url  = piwik.piwik_url;
+        $scope.period = piwik.period;
 
-    $scope.sortBy = function (metric) {
+        $scope.sortBy = function (metric) {
 
-        var reverse = $scope.reverse;
-        if ($scope.predicate == metric) {
-            reverse = !reverse;
-        }
+            var reverse = $scope.reverse;
+            if ($scope.predicate == metric) {
+                reverse = !reverse;
+            }
 
-        $scope.predicate = metric;
-        $scope.reverse   = reverse;
-    };
+            $scope.predicate = metric;
+            $scope.reverse   = reverse;
+        };
 
-    this.refresh = function (interval) {
-        multisitesDashboardModel.fetchAllSites(interval);
-    };
-});
+        this.refresh = function (interval) {
+            multisitesDashboardModel.fetchAllSites(interval);
+        };
+    }
+})();
diff --git a/plugins/MultiSites/angularjs/dashboard/dashboard-directive.js b/plugins/MultiSites/angularjs/dashboard/dashboard-directive.js
index 6f24c833e1..830da3deb5 100644
--- a/plugins/MultiSites/angularjs/dashboard/dashboard-directive.js
+++ b/plugins/MultiSites/angularjs/dashboard/dashboard-directive.js
@@ -17,24 +17,28 @@
  *      auto-refresh-today-report="500" // or 0 to disable
  * ></div>
  */
-angular.module('piwikApp').directive('piwikMultisitesDashboard', function($document, piwik, $filter){
+(function () {
+    angular.module('piwikApp').directive('piwikMultisitesDashboard', piwikMultisitesDashboard);
 
-    return {
-        restrict: 'A',
-        scope: {
-            displayRevenueColumn: '@',
-            showSparklines: '@',
-            dateSparkline: '@'
-        },
-        templateUrl: 'plugins/MultiSites/angularjs/dashboard/dashboard.html?cb=' + piwik.cacheBuster,
-        controller: 'MultiSitesDashboardController',
-        link: function (scope, element, attrs, controller) {
+    function piwikMultisitesDashboard($document, piwik, $filter){
 
-            if (attrs.pageSize) {
-                scope.model.pageSize = attrs.pageSize;
-            }
+        return {
+            restrict: 'A',
+            scope: {
+                displayRevenueColumn: '@',
+                showSparklines: '@',
+                dateSparkline: '@'
+            },
+            templateUrl: 'plugins/MultiSites/angularjs/dashboard/dashboard.html?cb=' + piwik.cacheBuster,
+            controller: 'MultiSitesDashboardController',
+            link: function (scope, element, attrs, controller) {
+
+                if (attrs.pageSize) {
+                    scope.model.pageSize = attrs.pageSize;
+                }
 
-            controller.refresh(attrs.autoRefreshTodayReport);
-        }
-    };
-});
\ No newline at end of file
+                controller.refresh(attrs.autoRefreshTodayReport);
+            }
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/MultiSites/angularjs/dashboard/dashboard-filter.js b/plugins/MultiSites/angularjs/dashboard/dashboard-filter.js
index 1ef4b2fd0d..b8f9040e9b 100644
--- a/plugins/MultiSites/angularjs/dashboard/dashboard-filter.js
+++ b/plugins/MultiSites/angularjs/dashboard/dashboard-filter.js
@@ -24,40 +24,44 @@
  * - website5
  * - website6
  */
-angular.module('piwikApp').filter('multiSitesGroupFilter', function() {
-    return function(websites, from, to) {
-        var offsetEnd = parseInt(from, 10) + parseInt(to, 10);
-        var groups    = {};
-
-        var sites = [];
-        for (var index = 0; index < websites.length; index++) {
-            var website = websites[index];
-
-            sites.push(website);
-            if (website.sites && website.sites.length) {
-                groups[website.label] = website;
-                for (var innerIndex = 0; innerIndex < website.sites.length; innerIndex++) {
-                    sites.push(website.sites[innerIndex]);
+(function () {
+    angular.module('piwikApp').filter('multiSitesGroupFilter', multiSitesGroupFilter);
+
+    function multiSitesGroupFilter() {
+        return function(websites, from, to) {
+            var offsetEnd = parseInt(from, 10) + parseInt(to, 10);
+            var groups    = {};
+
+            var sites = [];
+            for (var index = 0; index < websites.length; index++) {
+                var website = websites[index];
+
+                sites.push(website);
+                if (website.sites && website.sites.length) {
+                    groups[website.label] = website;
+                    for (var innerIndex = 0; innerIndex < website.sites.length; innerIndex++) {
+                        sites.push(website.sites[innerIndex]);
+                    }
                 }
-            }
 
-            if (sites.length >= offsetEnd) {
-                break;
+                if (sites.length >= offsetEnd) {
+                    break;
+                }
             }
-        }
 
-        // if the first site is a website having a group, then try to find the related group and prepend it to the list
-        // of sites to make sure we always display the name of the group that belongs to a website.
-        var filteredSites = sites.slice(from, offsetEnd);
+            // if the first site is a website having a group, then try to find the related group and prepend it to the list
+            // of sites to make sure we always display the name of the group that belongs to a website.
+            var filteredSites = sites.slice(from, offsetEnd);
 
-        if (filteredSites.length && filteredSites[0] && filteredSites[0].group) {
-            var groupName = filteredSites[0].group;
-            if (groups[groupName]) {
-                filteredSites.unshift(groups[groupName]);
+            if (filteredSites.length && filteredSites[0] && filteredSites[0].group) {
+                var groupName = filteredSites[0].group;
+                if (groups[groupName]) {
+                    filteredSites.unshift(groups[groupName]);
+                }
             }
-        }
 
-        return filteredSites;
-    };
-});
+            return filteredSites;
+        };
+    }
+})();
 
diff --git a/plugins/MultiSites/angularjs/dashboard/dashboard-model.js b/plugins/MultiSites/angularjs/dashboard/dashboard-model.js
index f2c46c61d4..7643249613 100644
--- a/plugins/MultiSites/angularjs/dashboard/dashboard-model.js
+++ b/plugins/MultiSites/angularjs/dashboard/dashboard-model.js
@@ -1,300 +1,313 @@
 /**
  * Model for Multisites Dashboard aka All Websites Dashboard.
- *
  */
-angular.module('piwikApp').factory('multisitesDashboardModel', function (piwikApi, $filter, $timeout) {
-    /**
-     *
-     * this is the list of all available sites. For performance reason this list is different to model.sites. ngRepeat
-     * won't operate on the whole list this way. The allSites array contains websites and groups in the following
-     * structure
-     *
-     * - website1
-     * - website2
-     * - website3.sites = [ // this is a group
-     *    - website4
-     *    - website5
-     * ]
-     * - website6
-     *
-     * This structure allows us to display the sites within a group directly under the group without big logic and also
-     * allows us to calculate the summary for each group easily
-    */
-    var allSitesByGroup = [];
-
-    var model       = {};
-    // those sites are going to be displayed
-    model.sites     = [];
-    model.isLoading = false;
-    model.pageSize  = 5;
-    model.currentPage  = 0;
-    model.totalVisits  = '?';
-    model.totalActions = '?';
-    model.totalRevenue = '?';
-    model.searchTerm   = '';
-    model.lastVisits   = '?';
-    model.lastVisitsDate = '?';
-
-    fetchPreviousSummary();
-
-    // create a new group object which has similar structure than a website
-    function createGroup(name){
-        return {
-            label: name,
-            sites: [],
-            nb_visits: 0,
-            nb_pageviews: 0,
-            revenue: 0,
-            isGroup: true
+(function () {
+    angular.module('piwikApp').factory('multisitesDashboardModel', multisitesDashboardModel);
+
+    function multisitesDashboardModel(piwikApi, $filter, $timeout) {
+        /**
+         *
+         * this is the list of all available sites. For performance reason this list is different to model.sites. ngRepeat
+         * won't operate on the whole list this way. The allSites array contains websites and groups in the following
+         * structure
+         *
+         * - website1
+         * - website2
+         * - website3.sites = [ // this is a group
+         *    - website4
+         *    - website5
+         * ]
+         * - website6
+         *
+         * This structure allows us to display the sites within a group directly under the group without big logic and also
+         * allows us to calculate the summary for each group easily
+         */
+        var allSitesByGroup = [];
+
+        // those sites are going to be displayed
+        var model = {
+            sites        : [],
+            isLoading    : false,
+            pageSize     : 5,
+            currentPage  : 0,
+            totalVisits  : '?',
+            totalActions : '?',
+            totalRevenue : '?',
+            searchTerm   : '',
+            lastVisits   : '?',
+            lastVisitsDate : '?',
+            updateWebsitesList: updateWebsitesList,
+            getNumberOfFilteredSites: getNumberOfFilteredSites,
+            getNumberOfPages: getNumberOfPages,
+            getCurrentPagingOffsetStart: getCurrentPagingOffsetStart,
+            getCurrentPagingOffsetEnd: getCurrentPagingOffsetEnd,
+            previousPage: previousPage,
+            nextPage: nextPage,
+            searchSite: searchSite,
+            fetchAllSites: fetchAllSites
         };
-    }
 
-    // create a new group with empty site to make sure we do not change the original group in $allSites
-    function copyGroup(group)
-    {
-        return {
-            label: group.label,
-            sites: [],
-            nb_visits: group.nb_visits,
-            nb_pageviews: group.nb_pageviews,
-            revenue: group.revenue,
-            isGroup: true
-        };
-    }
+        fetchPreviousSummary();
 
-    function onError () {
-        model.errorLoadingSites = true;
-        model.sites     = [];
-        allSitesByGroup = [];
-    }
+        return model;
 
-    function calculateMetricsForEachGroup(groups)
-    {
-        angular.forEach(groups, function (group) {
-            angular.forEach(group.sites, function (site) {
-                var revenue = 0;
-                if (site.revenue) {
-                    revenue = (site.revenue+'').match(/(\d+\.?\d*)/); // convert $ 0.00 to 0.00 or 5€ to 5
-                }
+        // create a new group object which has similar structure than a website
+        function createGroup(name){
+            return {
+                label: name,
+                sites: [],
+                nb_visits: 0,
+                nb_pageviews: 0,
+                revenue: 0,
+                isGroup: true
+            };
+        }
 
-                group.nb_visits    += parseInt(site.nb_visits, 10);
-                group.nb_pageviews += parseInt(site.nb_pageviews, 10);
-                if (revenue.length) {
-                    group.revenue += parseInt(revenue[0], 10);
-                }
+        // create a new group with empty site to make sure we do not change the original group in $allSites
+        function copyGroup(group)
+        {
+            return {
+                label: group.label,
+                sites: [],
+                nb_visits: group.nb_visits,
+                nb_pageviews: group.nb_pageviews,
+                revenue: group.revenue,
+                isGroup: true
+            };
+        }
+
+        function onError () {
+            model.errorLoadingSites = true;
+            model.sites     = [];
+            allSitesByGroup = [];
+        }
+
+        function calculateMetricsForEachGroup(groups)
+        {
+            angular.forEach(groups, function (group) {
+                angular.forEach(group.sites, function (site) {
+                    var revenue = 0;
+                    if (site.revenue) {
+                        revenue = (site.revenue+'').match(/(\d+\.?\d*)/); // convert $ 0.00 to 0.00 or 5€ to 5
+                    }
+
+                    group.nb_visits    += parseInt(site.nb_visits, 10);
+                    group.nb_pageviews += parseInt(site.nb_pageviews, 10);
+                    if (revenue.length) {
+                        group.revenue += parseInt(revenue[0], 10);
+                    }
+                });
             });
-        });
-    }
+        }
 
-    function createGroupsAndMoveSitesIntoRelatedGroup(allSitesUnordered, reportMetadata)
-    {
-        var sitesByGroup = [];
-        var groups = {};
-
-        // we do 3 things (complete site information, create groups, move sites into group) in one step for
-        // performance reason, there can be > 20k sites
-        angular.forEach(allSitesUnordered, function (site, index) {
-            site.idsite   = reportMetadata[index].idsite;
-            site.group    = reportMetadata[index].group;
-            site.main_url = reportMetadata[index].main_url;
-            // casting evolution to int fixes sorting, see: https://github.com/piwik/piwik/issues/4885
-            site.visits_evolution    = parseInt(site.visits_evolution, 10);
-            site.pageviews_evolution = parseInt(site.pageviews_evolution, 10);
-            site.revenue_evolution   = parseInt(site.revenue_evolution, 10);
-
-            if (site.group) {
-
-                if (!groups[site.group]) {
-                    var group = createGroup(site.group);
-
-                    groups[site.group] = group;
-                    sitesByGroup.push(group);
-                }
+        function createGroupsAndMoveSitesIntoRelatedGroup(allSitesUnordered, reportMetadata)
+        {
+            var sitesByGroup = [];
+            var groups = {};
 
-                groups[site.group].sites.push(site);
+            // we do 3 things (complete site information, create groups, move sites into group) in one step for
+            // performance reason, there can be > 20k sites
+            angular.forEach(allSitesUnordered, function (site, index) {
+                site.idsite   = reportMetadata[index].idsite;
+                site.group    = reportMetadata[index].group;
+                site.main_url = reportMetadata[index].main_url;
+                // casting evolution to int fixes sorting, see: https://github.com/piwik/piwik/issues/4885
+                site.visits_evolution    = parseInt(site.visits_evolution, 10);
+                site.pageviews_evolution = parseInt(site.pageviews_evolution, 10);
+                site.revenue_evolution   = parseInt(site.revenue_evolution, 10);
 
-            } else {
-                sitesByGroup.push(site);
-            }
-        });
+                if (site.group) {
 
-        calculateMetricsForEachGroup(groups);
+                    if (!groups[site.group]) {
+                        var group = createGroup(site.group);
 
-        return sitesByGroup;
-    }
+                        groups[site.group] = group;
+                        sitesByGroup.push(group);
+                    }
 
-    function getSumTotalActions(allSitesUnordered)
-    {
-        var totalActions = 0;
+                    groups[site.group].sites.push(site);
 
-        if (allSitesUnordered && allSitesUnordered.length) {
-            for (var index in allSitesUnordered) {
-                var site = allSitesUnordered[index];
-                if (site && site.nb_pageviews) {
-                    totalActions += parseInt(site.nb_pageviews, 10);
+                } else {
+                    sitesByGroup.push(site);
                 }
-            }
+            });
+
+            calculateMetricsForEachGroup(groups);
+
+            return sitesByGroup;
         }
 
-        return totalActions;
-    }
+        function getSumTotalActions(allSitesUnordered)
+        {
+            var totalActions = 0;
+
+            if (allSitesUnordered && allSitesUnordered.length) {
+                for (var index in allSitesUnordered) {
+                    var site = allSitesUnordered[index];
+                    if (site && site.nb_pageviews) {
+                        totalActions += parseInt(site.nb_pageviews, 10);
+                    }
+                }
+            }
 
-    model.updateWebsitesList = function (processedReport) {
-        if (!processedReport) {
-            onError();
-            return;
+            return totalActions;
         }
 
-        var allSitesUnordered = processedReport.reportData;
+        function updateWebsitesList(processedReport) {
+            if (!processedReport) {
+                onError();
+                return;
+            }
 
-        model.totalActions = getSumTotalActions(allSitesUnordered);
-        model.totalVisits  = processedReport.reportTotal.nb_visits;
-        model.totalRevenue = processedReport.reportTotal.revenue;
+            var allSitesUnordered = processedReport.reportData;
 
-        allSitesByGroup = createGroupsAndMoveSitesIntoRelatedGroup(allSitesUnordered, processedReport.reportMetadata);
+            model.totalActions = getSumTotalActions(allSitesUnordered);
+            model.totalVisits  = processedReport.reportTotal.nb_visits;
+            model.totalRevenue = processedReport.reportTotal.revenue;
 
-        if (!allSitesByGroup.length) {
-            return;
-        }
+            allSitesByGroup = createGroupsAndMoveSitesIntoRelatedGroup(allSitesUnordered, processedReport.reportMetadata);
 
-        if (model.searchTerm) {
-            model.searchSite(model.searchTerm);
-        } else {
-            model.sites = allSitesByGroup;
+            if (!allSitesByGroup.length) {
+                return;
+            }
+
+            if (model.searchTerm) {
+                searchSite(model.searchTerm);
+            } else {
+                model.sites = allSitesByGroup;
+            }
         }
-    };
 
-    model.getNumberOfFilteredSites = function () {
-        var numSites = model.sites.length;
+        function getNumberOfFilteredSites () {
+            var numSites = model.sites.length;
 
-        var groupNames = {};
+            var groupNames = {};
 
-        for (var index = 0; index < model.sites.length; index++) {
-            var site = model.sites[index];
-            if (site && site.isGroup) {
-                numSites += site.sites.length;
+            for (var index = 0; index < model.sites.length; index++) {
+                var site = model.sites[index];
+                if (site && site.isGroup) {
+                    numSites += site.sites.length;
+                }
             }
+
+            return numSites;
+        }
+
+        function getNumberOfPages() {
+            return Math.ceil(getNumberOfFilteredSites() / model.pageSize - 1);
         }
 
-        return numSites;
-    };
+        function getCurrentPagingOffsetStart() {
+            return Math.ceil(model.currentPage * model.pageSize);
+        }
 
-    model.getNumberOfPages = function () {
-        return Math.ceil(model.getNumberOfFilteredSites() / model.pageSize - 1);
-    };
+        function getCurrentPagingOffsetEnd() {
+            var end = getCurrentPagingOffsetStart() + parseInt(model.pageSize, 10);
+            var max = getNumberOfFilteredSites();
+            if (end > max) {
+                end = max;
+            }
+            return parseInt(end, 10);
+        }
 
-    model.getCurrentPagingOffsetStart = function() {
-        return Math.ceil(model.currentPage * model.pageSize);
-    };
+        function previousPage() {
+            model.currentPage = model.currentPage - 1;
+        }
 
-    model.getCurrentPagingOffsetEnd = function() {
-        var end = model.getCurrentPagingOffsetStart() + parseInt(model.pageSize, 10);
-        var max = model.getNumberOfFilteredSites();
-        if (end > max) {
-            end = max;
+        function nextPage() {
+            model.currentPage = model.currentPage + 1;
         }
-        return parseInt(end, 10);
-    };
-
-    model.previousPage = function () {
-        model.currentPage = model.currentPage - 1;
-    };
-
-    model.nextPage = function () {
-        model.currentPage = model.currentPage + 1;
-    };
-
-    function nestedSearch(sitesByGroup, term)
-    {
-        var filteredSites = [];
-
-        term = term.toLowerCase();
-
-        for (var index in sitesByGroup) {
-            var site = sitesByGroup[index];
-            if (site.isGroup) {
-                var matchingSites = nestedSearch(site.sites, term);
-                if (matchingSites.length || (''+site.label).toLowerCase().indexOf(term) > -1) {
-                    var clonedGroup   = copyGroup(site);
-                    clonedGroup.sites = matchingSites;
-                    filteredSites.push(clonedGroup);
+
+        function nestedSearch(sitesByGroup, term)
+        {
+            var filteredSites = [];
+
+            term = term.toLowerCase();
+
+            for (var index in sitesByGroup) {
+                var site = sitesByGroup[index];
+                if (site.isGroup) {
+                    var matchingSites = nestedSearch(site.sites, term);
+                    if (matchingSites.length || (''+site.label).toLowerCase().indexOf(term) > -1) {
+                        var clonedGroup   = copyGroup(site);
+                        clonedGroup.sites = matchingSites;
+                        filteredSites.push(clonedGroup);
+                    }
+                } else if ((''+site.label).toLowerCase().indexOf(term) > -1) {
+                    filteredSites.push(site);
+                } else if (site.group && (''+site.group).toLowerCase().indexOf(term) > -1) {
+                    filteredSites.push(site);
                 }
-            } else if ((''+site.label).toLowerCase().indexOf(term) > -1) {
-                filteredSites.push(site);
-            } else if (site.group && (''+site.group).toLowerCase().indexOf(term) > -1) {
-                filteredSites.push(site);
             }
+
+            return filteredSites;
         }
 
-        return filteredSites;
-    }
+        function searchSite (term) {
+            model.searchTerm  = term;
+            model.currentPage = 0;
+            model.sites       = nestedSearch(allSitesByGroup, term);
+        }
 
-    model.searchSite = function (term) {
-        model.searchTerm  = term;
-        model.currentPage = 0;
-        model.sites       = nestedSearch(allSitesByGroup, term);
-    };
-
-    function fetchPreviousSummary () {
-        piwikApi.fetch({
-            method: 'API.getLastDate'
-        }).then(function (response) {
-            if (response && response.value) {
-                return response.value;
-            }
-        }).then(function (lastDate) {
-            if (!lastDate) {
-                return;
+        function fetchPreviousSummary () {
+            piwikApi.fetch({
+                method: 'API.getLastDate'
+            }).then(function (response) {
+                if (response && response.value) {
+                    return response.value;
+                }
+            }).then(function (lastDate) {
+                if (!lastDate) {
+                    return;
+                }
+
+                model.lastVisitsDate = lastDate;
+
+                return piwikApi.fetch({
+                    method: 'API.getProcessedReport',
+                    apiModule: 'MultiSites',
+                    apiAction: 'getAll',
+                    hideMetricsDoc: '1',
+                    filter_limit: '0',
+                    showColumns: 'label,nb_visits',
+                    enhanced: 1,
+                    date: lastDate
+                });
+            }).then(function (response) {
+                if (response && response.reportTotal) {
+                    model.lastVisits = response.reportTotal.nb_visits;
+                }
+            });
+        }
+
+        function fetchAllSites(refreshInterval) {
+
+            if (model.isLoading) {
+                piwikApi.abort();
             }
 
-            model.lastVisitsDate = lastDate;
+            model.isLoading = true;
+            model.errorLoadingSites = false;
 
             return piwikApi.fetch({
                 method: 'API.getProcessedReport',
                 apiModule: 'MultiSites',
                 apiAction: 'getAll',
                 hideMetricsDoc: '1',
-                filter_limit: '0',
-                showColumns: 'label,nb_visits',
-                enhanced: 1,
-                date: lastDate
+                filter_limit: '-1',
+                showColumns: 'label,nb_visits,nb_pageviews,visits_evolution,pageviews_evolution,revenue_evolution,nb_actions,revenue',
+                enhanced: 1
+            }).then(function (response) {
+                updateWebsitesList(response);
+            }, onError)['finally'](function () {
+                model.isLoading = false;
+
+                if (refreshInterval && refreshInterval > 0) {
+                    $timeout(function () {
+                        fetchAllSites(refreshInterval);
+                    }, refreshInterval * 1000);
+                }
             });
-        }).then(function (response) {
-            if (response && response.reportTotal) {
-                model.lastVisits = response.reportTotal.nb_visits;
-            }
-        });
-    }
-
-    model.fetchAllSites = function (refreshInterval) {
-
-        if (model.isLoading) {
-            piwikApi.abort();
         }
-
-        model.isLoading = true;
-        model.errorLoadingSites = false;
-
-        return piwikApi.fetch({
-            method: 'API.getProcessedReport',
-            apiModule: 'MultiSites',
-            apiAction: 'getAll',
-            hideMetricsDoc: '1',
-            filter_limit: '-1',
-            showColumns: 'label,nb_visits,nb_pageviews,visits_evolution,pageviews_evolution,revenue_evolution,nb_actions,revenue',
-            enhanced: 1
-        }).then(function (response) {
-            model.updateWebsitesList(response);
-        }, onError)['finally'](function () {
-            model.isLoading = false;
-
-            if (refreshInterval && refreshInterval > 0) {
-                $timeout(function () {
-                    model.fetchAllSites(refreshInterval);
-                }, refreshInterval * 1000);
-            }
-        });
-    };
-
-    return model;
-});
+    }
+})();
diff --git a/plugins/MultiSites/angularjs/site/site-directive.js b/plugins/MultiSites/angularjs/site/site-directive.js
index 66863d6a06..53ca61fb71 100644
--- a/plugins/MultiSites/angularjs/site/site-directive.js
+++ b/plugins/MultiSites/angularjs/site/site-directive.js
@@ -17,38 +17,42 @@
  *     display-revenue-column="true"
  *     </div>
  */
-angular.module('piwikApp').directive('piwikMultisitesSite', function($document, piwik, $filter){
+(function () {
+    angular.module('piwikApp').directive('piwikMultisitesSite', piwikMultisitesSite);
 
-    return {
-        restrict: 'AC',
-        replace: true,
-        scope: {
-            website: '=',
-            evolutionMetric: '=',
-            showSparklines: '=',
-            dateSparkline: '=',
-            displayRevenueColumn: '=',
-            metric: '='
-        },
-        templateUrl: 'plugins/MultiSites/angularjs/site/site.html?cb=' + piwik.cacheBuster,
-        controller: function ($scope) {
+    function piwikMultisitesSite($document, piwik, $filter){
 
-            $scope.period   = piwik.period;
-            $scope.date     = piwik.broadcast.getValueFromUrl('date');
+        return {
+            restrict: 'AC',
+            replace: true,
+            scope: {
+                website: '=',
+                evolutionMetric: '=',
+                showSparklines: '=',
+                dateSparkline: '=',
+                displayRevenueColumn: '=',
+                metric: '='
+            },
+            templateUrl: 'plugins/MultiSites/angularjs/site/site.html?cb=' + piwik.cacheBuster,
+            controller: function ($scope) {
 
-            this.getWebsite = function () {
-                return $scope.website;
-            };
+                $scope.period   = piwik.period;
+                $scope.date     = piwik.broadcast.getValueFromUrl('date');
 
-            $scope.sparklineImage = function(website){
-                var append = '';
-                var token_auth = piwik.broadcast.getValueFromUrl('token_auth');
-                if (token_auth.length) {
-                    append = '&token_auth=' + token_auth;
-                }
+                this.getWebsite = function () {
+                    return $scope.website;
+                };
 
-                return piwik.piwik_url + '?module=MultiSites&action=getEvolutionGraph&period=' + $scope.period + '&date=' + $scope.dateSparkline + '&evolutionBy=' +$scope.metric + '&columns=' + $scope.metric + '&idSite=' + website.idsite + '&idsite=' + website.idsite + '&viewDataTable=sparkline' + append + '&colors=' + encodeURIComponent(JSON.stringify(piwik.getSparklineColors()));
-            };
-        }
-    };
-});
\ No newline at end of file
+                $scope.sparklineImage = function(website){
+                    var append = '';
+                    var token_auth = piwik.broadcast.getValueFromUrl('token_auth');
+                    if (token_auth.length) {
+                        append = '&token_auth=' + token_auth;
+                    }
+
+                    return piwik.piwik_url + '?module=MultiSites&action=getEvolutionGraph&period=' + $scope.period + '&date=' + $scope.dateSparkline + '&evolutionBy=' +$scope.metric + '&columns=' + $scope.metric + '&idSite=' + website.idsite + '&idsite=' + website.idsite + '&viewDataTable=sparkline' + append + '&colors=' + encodeURIComponent(JSON.stringify(piwik.getSparklineColors()));
+                };
+            }
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/SitesManager/javascripts/sites-manager-controller.js b/plugins/SitesManager/javascripts/sites-manager-controller.js
index 6da2f511e4..aa5f7437d4 100644
--- a/plugins/SitesManager/javascripts/sites-manager-controller.js
+++ b/plugins/SitesManager/javascripts/sites-manager-controller.js
@@ -4,241 +4,244 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp').controller('SitesManagerController', SitesManagerController);
 
-angular.module('piwikApp').controller('SitesManagerController', function ($scope, $filter, coreAPI, coreAdminAPI, sitesManagerAPI, piwik, sitesManagerApiHelper) {
+    function SitesManagerController($scope, $filter, coreAPI, coreAdminAPI, sitesManagerAPI, piwik, sitesManagerApiHelper) {
 
-    var translate = $filter('translate');
+        var translate = $filter('translate');
 
-    var init = function () {
+        var init = function () {
 
-        initModel();
-        initActions();
-    };
+            initModel();
+            initActions();
+        };
 
-    var initModel = function() {
+        var initModel = function() {
 
-        $scope.sites = [];
-        $scope.hasSuperUserAccess = piwik.hasSuperUserAccess;
-        $scope.redirectParams = {showaddsite: false};
+            $scope.sites = [];
+            $scope.hasSuperUserAccess = piwik.hasSuperUserAccess;
+            $scope.redirectParams = {showaddsite: false};
 
-        initSelectLists();
-        initUtcTime();
-        initUserIP();
-        initCustomVariablesActivated();
-        initIsTimezoneSupportEnabled();
-        initGlobalParams();
-    };
+            initSelectLists();
+            initUtcTime();
+            initUserIP();
+            initCustomVariablesActivated();
+            initIsTimezoneSupportEnabled();
+            initGlobalParams();
+        };
 
-    var initActions = function () {
+        var initActions = function () {
 
-        $scope.cancelEditSite = cancelEditSite;
-        $scope.addSite = addSite;
-        $scope.saveGlobalSettings = saveGlobalSettings;
+            $scope.cancelEditSite = cancelEditSite;
+            $scope.addSite = addSite;
+            $scope.saveGlobalSettings = saveGlobalSettings;
 
-        $scope.informSiteIsBeingEdited = informSiteIsBeingEdited;
-        $scope.lookupCurrentEditSite = lookupCurrentEditSite;
-    };
+            $scope.informSiteIsBeingEdited = informSiteIsBeingEdited;
+            $scope.lookupCurrentEditSite = lookupCurrentEditSite;
+        };
 
-    var informSiteIsBeingEdited = function() {
+        var informSiteIsBeingEdited = function() {
 
-        $scope.siteIsBeingEdited = true;
-    };
+            $scope.siteIsBeingEdited = true;
+        };
 
-    var initSelectLists = function() {
+        var initSelectLists = function() {
 
-        initSiteSearchSelectOptions();
-        initEcommerceSelectOptions();
-        initCurrencyList();
-        initTimezones();
-    };
+            initSiteSearchSelectOptions();
+            initEcommerceSelectOptions();
+            initCurrencyList();
+            initTimezones();
+        };
 
-    var initGlobalParams = function() {
+        var initGlobalParams = function() {
 
-        showLoading();
+            showLoading();
 
-        sitesManagerAPI.getGlobalSettings(function(globalSettings) {
+            sitesManagerAPI.getGlobalSettings(function(globalSettings) {
 
-            $scope.globalSettings = globalSettings;
+                $scope.globalSettings = globalSettings;
 
-            $scope.globalSettings.searchKeywordParametersGlobal = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.globalSettings.searchKeywordParametersGlobal);
-            $scope.globalSettings.searchCategoryParametersGlobal = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.globalSettings.searchCategoryParametersGlobal);
-            $scope.globalSettings.excludedIpsGlobal = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.globalSettings.excludedIpsGlobal);
-            $scope.globalSettings.excludedQueryParametersGlobal = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.globalSettings.excludedQueryParametersGlobal);
-            $scope.globalSettings.excludedUserAgentsGlobal = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.globalSettings.excludedUserAgentsGlobal);
+                $scope.globalSettings.searchKeywordParametersGlobal = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.globalSettings.searchKeywordParametersGlobal);
+                $scope.globalSettings.searchCategoryParametersGlobal = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.globalSettings.searchCategoryParametersGlobal);
+                $scope.globalSettings.excludedIpsGlobal = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.globalSettings.excludedIpsGlobal);
+                $scope.globalSettings.excludedQueryParametersGlobal = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.globalSettings.excludedQueryParametersGlobal);
+                $scope.globalSettings.excludedUserAgentsGlobal = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.globalSettings.excludedUserAgentsGlobal);
 
-            initKeepURLFragmentsList();
+                initKeepURLFragmentsList();
 
-            initSiteList();
+                initSiteList();
 
-            triggerAddSiteIfRequested();
-        });
-    };
+                triggerAddSiteIfRequested();
+            });
+        };
 
-    var triggerAddSiteIfRequested = function() {
+        var triggerAddSiteIfRequested = function() {
 
-        if(piwikHelper.getArrayFromQueryString(String(window.location.search))['showaddsite'] == 1)
-            addSite();
-    };
+            if(piwikHelper.getArrayFromQueryString(String(window.location.search))['showaddsite'] == 1)
+                addSite();
+        };
 
-    var initEcommerceSelectOptions = function() {
+        var initEcommerceSelectOptions = function() {
 
-        $scope.eCommerceptions = [
-            {key: '0', value: translate('SitesManager_NotAnEcommerceSite')},
-            {key: '1', value: translate('SitesManager_EnableEcommerce')}
-        ];
-    };
+            $scope.eCommerceptions = [
+                {key: '0', value: translate('SitesManager_NotAnEcommerceSite')},
+                {key: '1', value: translate('SitesManager_EnableEcommerce')}
+            ];
+        };
 
-    var initUtcTime = function() {
+        var initUtcTime = function() {
 
-        var currentDate = new Date();
+            var currentDate = new Date();
 
-        $scope.utcTime =  new Date(
-            currentDate.getUTCFullYear(),
-            currentDate.getUTCMonth(),
-            currentDate.getUTCDate(),
-            currentDate.getUTCHours(),
-            currentDate.getUTCMinutes(),
-            currentDate.getUTCSeconds()
-        );
-    };
+            $scope.utcTime =  new Date(
+                currentDate.getUTCFullYear(),
+                currentDate.getUTCMonth(),
+                currentDate.getUTCDate(),
+                currentDate.getUTCHours(),
+                currentDate.getUTCMinutes(),
+                currentDate.getUTCSeconds()
+            );
+        };
 
-    var initIsTimezoneSupportEnabled = function() {
+        var initIsTimezoneSupportEnabled = function() {
 
-        sitesManagerAPI.isTimezoneSupportEnabled(function (timezoneSupportEnabled) {
-            $scope.timezoneSupportEnabled = timezoneSupportEnabled;
-        });
-    };
+            sitesManagerAPI.isTimezoneSupportEnabled(function (timezoneSupportEnabled) {
+                $scope.timezoneSupportEnabled = timezoneSupportEnabled;
+            });
+        };
 
-    var initTimezones = function() {
+        var initTimezones = function() {
 
-        sitesManagerAPI.getTimezonesList(
+            sitesManagerAPI.getTimezonesList(
 
-            function (timezones) {
+                function (timezones) {
 
-                $scope.timezones = [];
+                    $scope.timezones = [];
 
-                angular.forEach(timezones, function(groupTimezones, timezoneGroup) {
+                    angular.forEach(timezones, function(groupTimezones, timezoneGroup) {
 
-                    angular.forEach(groupTimezones, function(label, code) {
+                        angular.forEach(groupTimezones, function(label, code) {
 
-                        $scope.timezones.push({
-                           group: timezoneGroup,
-                           code: code,
-                           label: label
+                            $scope.timezones.push({
+                                group: timezoneGroup,
+                                code: code,
+                                label: label
+                            });
                         });
                     });
-                });
-            }
-        );
-    };
-
-    var initCustomVariablesActivated = function() {
-
-        coreAdminAPI.isPluginActivated(
+                }
+            );
+        };
 
-            function (customVariablesActivated) {
-                $scope.customVariablesActivated = customVariablesActivated;
-            },
+        var initCustomVariablesActivated = function() {
 
-            {pluginName: 'CustomVariables'}
-        );
-    };
+            coreAdminAPI.isPluginActivated(
 
-    var initUserIP = function() {
+                function (customVariablesActivated) {
+                    $scope.customVariablesActivated = customVariablesActivated;
+                },
 
-        coreAPI.getIpFromHeader(function(ip) {
-            $scope.currentIpAddress = ip;
-        });
-    };
+                {pluginName: 'CustomVariables'}
+            );
+        };
 
-    var initSiteSearchSelectOptions = function() {
+        var initUserIP = function() {
 
-        $scope.siteSearchOptions = [
-            {key: '1', value: translate('SitesManager_EnableSiteSearch')},
-            {key: '0', value: translate('SitesManager_DisableSiteSearch')}
-        ];
-    };
+            coreAPI.getIpFromHeader(function(ip) {
+                $scope.currentIpAddress = ip;
+            });
+        };
 
-    var initKeepURLFragmentsList = function() {
+        var initSiteSearchSelectOptions = function() {
 
-        $scope.keepURLFragmentsOptions = {
-            0: ($scope.globalSettings.keepURLFragmentsGlobal ? translate('General_Yes') : translate('General_No')) + ' (' + translate('General_Default') + ')',
-            1: translate('General_Yes'),
-            2: translate('General_No')
+            $scope.siteSearchOptions = [
+                {key: '1', value: translate('SitesManager_EnableSiteSearch')},
+                {key: '0', value: translate('SitesManager_DisableSiteSearch')}
+            ];
         };
-    };
 
-    var addSite = function() {
-        $scope.sites.push({});
-    };
+        var initKeepURLFragmentsList = function() {
 
-    var saveGlobalSettings = function() {
-
-        var ajaxHandler = new ajaxHelper();
+            $scope.keepURLFragmentsOptions = {
+                0: ($scope.globalSettings.keepURLFragmentsGlobal ? translate('General_Yes') : translate('General_No')) + ' (' + translate('General_Default') + ')',
+                1: translate('General_Yes'),
+                2: translate('General_No')
+            };
+        };
 
-        ajaxHandler.addParams({
-            module: 'SitesManager',
-            format: 'json',
-            action: 'setGlobalSettings'
-        }, 'GET');
+        var addSite = function() {
+            $scope.sites.push({});
+        };
 
-        ajaxHandler.addParams({
-            timezone: $scope.globalSettings.defaultTimezone,
-            currency: $scope.globalSettings.defaultCurrency,
-            excludedIps: $scope.globalSettings.excludedIpsGlobal.join(','),
-            excludedQueryParameters: $scope.globalSettings.excludedQueryParametersGlobal.join(','),
-            excludedUserAgents: $scope.globalSettings.excludedUserAgentsGlobal.join(','),
-            keepURLFragments: $scope.globalSettings.keepURLFragmentsGlobal ? 1 : 0,
-            enableSiteUserAgentExclude: $scope.globalSettings.siteSpecificUserAgentExcludeEnabled ? 1 : 0,
-            searchKeywordParameters: $scope.globalSettings.searchKeywordParametersGlobal.join(','),
-            searchCategoryParameters: $scope.globalSettings.searchCategoryParametersGlobal.join(',')
-        }, 'POST');
+        var saveGlobalSettings = function() {
+
+            var ajaxHandler = new ajaxHelper();
+
+            ajaxHandler.addParams({
+                module: 'SitesManager',
+                format: 'json',
+                action: 'setGlobalSettings'
+            }, 'GET');
+
+            ajaxHandler.addParams({
+                timezone: $scope.globalSettings.defaultTimezone,
+                currency: $scope.globalSettings.defaultCurrency,
+                excludedIps: $scope.globalSettings.excludedIpsGlobal.join(','),
+                excludedQueryParameters: $scope.globalSettings.excludedQueryParametersGlobal.join(','),
+                excludedUserAgents: $scope.globalSettings.excludedUserAgentsGlobal.join(','),
+                keepURLFragments: $scope.globalSettings.keepURLFragmentsGlobal ? 1 : 0,
+                enableSiteUserAgentExclude: $scope.globalSettings.siteSpecificUserAgentExcludeEnabled ? 1 : 0,
+                searchKeywordParameters: $scope.globalSettings.searchKeywordParametersGlobal.join(','),
+                searchCategoryParameters: $scope.globalSettings.searchCategoryParametersGlobal.join(',')
+            }, 'POST');
+
+            ajaxHandler.redirectOnSuccess($scope.redirectParams);
+            ajaxHandler.setLoadingElement();
+            ajaxHandler.send(true);
+        };
 
-        ajaxHandler.redirectOnSuccess($scope.redirectParams);
-        ajaxHandler.setLoadingElement();
-        ajaxHandler.send(true);
-    };
+        var cancelEditSite = function ($event) {
+            $event.stopPropagation();
+            piwikHelper.redirect($scope.redirectParams);
+        };
 
-    var cancelEditSite = function ($event) {
-        $event.stopPropagation();
-        piwikHelper.redirect($scope.redirectParams);
-    };
+        var lookupCurrentEditSite = function () {
 
-    var lookupCurrentEditSite = function () {
+            var sitesInEditMode = $scope.sites.filter(function(site) {
+                return site.editMode;
+            });
 
-        var sitesInEditMode = $scope.sites.filter(function(site) {
-            return site.editMode;
-        });
+            return sitesInEditMode[0];
+        };
 
-        return sitesInEditMode[0];
-    };
+        var initSiteList = function () {
 
-    var initSiteList = function () {
+            sitesManagerAPI.getSitesWithAdminAccess(function (sites) {
 
-        sitesManagerAPI.getSitesWithAdminAccess(function (sites) {
+                angular.forEach(sites, function(site) {
+                    $scope.sites.push(site);
+                });
 
-            angular.forEach(sites, function(site) {
-                $scope.sites.push(site);
+                hideLoading();
             });
+        };
 
-            hideLoading();
-        });
-    };
-
-    var initCurrencyList = function () {
+        var initCurrencyList = function () {
 
-        sitesManagerAPI.getCurrencyList(function (currencies) {
-            $scope.currencies = currencies;
-        });
-    };
+            sitesManagerAPI.getCurrencyList(function (currencies) {
+                $scope.currencies = currencies;
+            });
+        };
 
-    var showLoading = function() {
-        $scope.loading = true;
-    };
+        var showLoading = function() {
+            $scope.loading = true;
+        };
 
-    var hideLoading = function() {
-        $scope.loading = false;
-    };
+        var hideLoading = function() {
+            $scope.loading = false;
+        };
 
-    init();
-});
+        init();
+    }
+})();
diff --git a/plugins/SitesManager/javascripts/sites-manager-directives.js b/plugins/SitesManager/javascripts/sites-manager-directives.js
index 2357d3da60..38c0357aa6 100644
--- a/plugins/SitesManager/javascripts/sites-manager-directives.js
+++ b/plugins/SitesManager/javascripts/sites-manager-directives.js
@@ -4,82 +4,87 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp').directive('sitesManagerMultilineField', sitesManagerMultilineField);
+    angular.module('piwikApp').directive('sitesManagerEditTrigger', sitesManagerEditTrigger);
+    angular.module('piwikApp').directive('sitesManagerScroll', sitesManagerScroll);
 
-angular.module('piwikApp').directive('sitesManagerMultilineField', function () {
+    function sitesManagerScroll () {
 
-    return {
-        restrict: 'A',
-        replace: true,
-        scope: {
-            managedValue: '=field',
-            rows: '@?',
-            cols: '@?'
-        },
-        templateUrl: 'plugins/SitesManager/templates/directives/multiline-field.html?cb=' + piwik.cacheBuster,
-        link: function (scope) {
+        return {
+            restrict: 'A',
+            link: function (scope, element) {
 
-            var separator = '\n';
+                scope.$watch('site.editMode', function() {
 
-            var init = function () {
+                    if(scope.site.editMode)
+                        scrollToSite();
+                });
 
-                scope.field = {};
-                scope.onChange = updateManagedScopeValue;
+                var scrollToSite = function() {
+                    piwikHelper.lazyScrollTo(element[0], 500, true);
+                };
+            }
+        };
+    }
 
-                scope.$watch('managedValue', updateInputValue);
-            };
+    function sitesManagerEditTrigger() {
 
-            var updateManagedScopeValue = function () {
-                scope.managedValue = scope.field.value.trim().split(separator);
-            };
+        return {
+            restrict: 'A',
+            link: function (scope, element) {
 
-            var updateInputValue = function () {
+                element.bind('click', function(){
 
-                if(angular.isUndefined(scope.managedValue))
-                    return;
+                    if(!scope.site.editMode)
+                        scope.$apply(scope.editSite());
+                });
 
-                scope.field.value = scope.managedValue.join(separator);
-            };
+                scope.$watch('site.editMode', function() {
 
-            init();
-        }
-    };
-});
+                    element.toggleClass('editable-site-field', !scope.site.editMode);
+                });
+            }
+        };
+    }
 
-angular.module('piwikApp').directive('sitesManagerEditTrigger', function () {
+    function sitesManagerMultilineField() {
 
-    return {
-        restrict: 'A',
-        link: function (scope, element) {
+        return {
+            restrict: 'A',
+            replace: true,
+            scope: {
+                managedValue: '=field',
+                rows: '@?',
+                cols: '@?'
+            },
+            templateUrl: 'plugins/SitesManager/templates/directives/multiline-field.html?cb=' + piwik.cacheBuster,
+            link: function (scope) {
 
-            element.bind('click', function(){
+                var separator = '\n';
 
-                if(!scope.site.editMode)
-                    scope.$apply(scope.editSite());
-            });
+                var init = function () {
 
-            scope.$watch('site.editMode', function() {
+                    scope.field = {};
+                    scope.onChange = updateManagedScopeValue;
 
-                element.toggleClass('editable-site-field', !scope.site.editMode);
-            });
-        }
-    };
-});
+                    scope.$watch('managedValue', updateInputValue);
+                };
 
-angular.module('piwikApp').directive('sitesManagerScroll', function () {
+                var updateManagedScopeValue = function () {
+                    scope.managedValue = scope.field.value.trim().split(separator);
+                };
 
-    return {
-        restrict: 'A',
-        link: function (scope, element) {
+                var updateInputValue = function () {
 
-            scope.$watch('site.editMode', function() {
+                    if(angular.isUndefined(scope.managedValue))
+                        return;
 
-                if(scope.site.editMode)
-                    scrollToSite();
-            });
+                    scope.field.value = scope.managedValue.join(separator);
+                };
 
-            var scrollToSite = function() {
-                piwikHelper.lazyScrollTo(element[0], 500, true);
-            };
-        }
-    };
-});
+                init();
+            }
+        };
+    }
+})();
diff --git a/plugins/SitesManager/javascripts/sites-manager-recipes.js b/plugins/SitesManager/javascripts/sites-manager-recipes.js
index 81bcaff97e..bec40a485c 100644
--- a/plugins/SitesManager/javascripts/sites-manager-recipes.js
+++ b/plugins/SitesManager/javascripts/sites-manager-recipes.js
@@ -4,92 +4,129 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp').factory('sitesManagerAPI', SitesManagerAPIFactory);
 
-angular.module('piwikApp').factory('sitesManagerAPI', function SitesManagerAPIFactory(sitesManagerApiHelper) {
+    // can probably be shared
+    angular.module('piwikApp').factory('coreAPI', CoreAPIFactory);
 
-    var api = sitesManagerApiHelper;
+    // can probably be shared
+    angular.module('piwikApp').factory('coreAdminAPI', CoreAdminAPIFactory);
 
-    return {
-        getCurrencyList: api.fetchApi('SitesManager.getCurrencyList', api.noop),
-        getSitesWithAdminAccess: api.fetchApi('SitesManager.getSitesWithAdminAccess', api.noop, {fetchAliasUrls: true}),
-        getTimezonesList: api.fetchApi('SitesManager.getTimezonesList', api.noop),
-        isTimezoneSupportEnabled: api.fetchApi('SitesManager.isTimezoneSupportEnabled', api.valueAdaptor),
-        getGlobalSettings: api.fetchAction('SitesManager', 'getGlobalSettings', api.noop)
-    };
-});
+    // can probably be renamed and shared
+    angular.module('piwikApp').factory('sitesManagerApiHelper', SitesManagerAPIHelperFactory);
 
-// can probably be shared
-angular.module('piwikApp').factory('coreAPI', function CoreAPIFactory(sitesManagerApiHelper) {
+    function SitesManagerAPIFactory(sitesManagerApiHelper) {
 
-    var api = sitesManagerApiHelper;
+        var api = sitesManagerApiHelper;
 
-    return {
-        getIpFromHeader: api.fetchApi('API.getIpFromHeader', api.valueAdaptor)
-    };
-});
+        return {
+            getCurrencyList: getCurrentcyList,
+            getSitesWithAdminAccess: getSitesWithAdminAccess,
+            getTimezonesList: getTimezonesList,
+            isTimezoneSupportEnabled: isTimezoneSupportEnabled,
+            getGlobalSettings: getGlobalSettings
+        };
 
-// can probably be shared
-angular.module('piwikApp').factory('coreAdminAPI', function CoreAdminAPIFactory(sitesManagerApiHelper) {
+        function getCurrencyList () {
+            return api.fetchApi('SitesManager.getCurrencyList', api.noop);
+        }
 
-    var api = sitesManagerApiHelper;
+        function getSitesWithAdminAccess () {
+            return api.fetchApi('SitesManager.getSitesWithAdminAccess', api.noop, {fetchAliasUrls: true});
+        }
 
-    return {
-        isPluginActivated: api.fetchApi('CoreAdminHome.isPluginActivated', api.valueAdaptor)
-    };
-});
+        function getTimezonesList () {
+            return api.fetchApi('SitesManager.getTimezonesList', api.noop);
+        }
+
+        function isTimezoneSupportEnabled () {
+            return api.fetchApi('SitesManager.isTimezoneSupportEnabled', api.valueAdaptor);
+        }
 
-// can probably be renamed and shared
-angular.module('piwikApp').factory('sitesManagerApiHelper', function SitesManagerAPIHelperFactory(piwikApi) {
+        function getGlobalSettings () {
+            return api.fetchAction('SitesManager', 'getGlobalSettings', api.noop);
+        }
+    }
 
-    return {
+    function CoreAPIFactory(sitesManagerApiHelper) {
 
-        fetch: function (endpoint, jsonResponseAdaptor, params) {
+        var api = sitesManagerApiHelper;
 
-            return function (clientHandover, additionalParams) {
+        return {
+            getIpFromHeader: getIpFromHeader
+        };
 
-                params = angular.extend(params || {}, additionalParams || {});
+        function getIpFromHeader() {
+            return api.fetchApi('API.getIpFromHeader', api.valueAdaptor);
+        }
+    }
 
-                var requestDefinition = angular.extend(endpoint, params);
+    function CoreAdminAPIFactory(sitesManagerApiHelper) {
 
-                var responseHandler = function (response) {
+        var api = sitesManagerApiHelper;
 
-                    response = jsonResponseAdaptor(response);
+        return {
+            isPluginActivated: isPluginActivated
+        };
 
-                    clientHandover(response);
-                };
+        function isPluginActivated() {
+            return api.fetchApi('CoreAdminHome.isPluginActivated', api.valueAdaptor);
+        }
+    }
 
-                piwikApi.fetch(requestDefinition).then(responseHandler);
-            }
-        },
+    function SitesManagerAPIHelperFactory(piwikApi) {
 
-        commaDelimitedFieldToArray: function(value) {
+        return {
 
-            if(value == null || value == '')
-                return [];
+            fetch: function (endpoint, jsonResponseAdaptor, params) {
 
-            return value.split(',');
-        },
+                return function (clientHandover, additionalParams) {
 
-        fetchApi: function (apiMethod, jsonResponseAdaptor, params) {
+                    params = angular.extend(params || {}, additionalParams || {});
 
-           return this.fetch({method: apiMethod}, jsonResponseAdaptor, params);
-        },
+                    var requestDefinition = angular.extend(endpoint, params);
 
-        fetchAction: function (module, action, jsonResponseAdaptor, params) {
+                    var responseHandler = function (response) {
 
-            return this.fetch({module: module, action: action}, jsonResponseAdaptor, params);
-        },
+                        response = jsonResponseAdaptor(response);
 
-        singleObjectAdaptor: function (response) {
-            return response[0];
-        },
+                        clientHandover(response);
+                    };
 
-        valueAdaptor: function (response) {
-            return response.value;
-        },
+                    piwikApi.fetch(requestDefinition).then(responseHandler);
+                }
+            },
 
-        noop: function (response) {
-            return response;
-        }
-    };
-});
+            commaDelimitedFieldToArray: function(value) {
+
+                if(value == null || value == '')
+                    return [];
+
+                return value.split(',');
+            },
+
+            fetchApi: function (apiMethod, jsonResponseAdaptor, params) {
+
+                return this.fetch({method: apiMethod}, jsonResponseAdaptor, params);
+            },
+
+            fetchAction: function (module, action, jsonResponseAdaptor, params) {
+
+                return this.fetch({module: module, action: action}, jsonResponseAdaptor, params);
+            },
+
+            singleObjectAdaptor: function (response) {
+                return response[0];
+            },
+
+            valueAdaptor: function (response) {
+                return response.value;
+            },
+
+            noop: function (response) {
+                return response;
+            }
+        };
+    }
+})();
diff --git a/plugins/SitesManager/javascripts/sites-manager-site-controller.js b/plugins/SitesManager/javascripts/sites-manager-site-controller.js
index c6ea22e45d..c0e271e2b7 100644
--- a/plugins/SitesManager/javascripts/sites-manager-site-controller.js
+++ b/plugins/SitesManager/javascripts/sites-manager-site-controller.js
@@ -4,161 +4,164 @@
  * @link http://piwik.org
  * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  */
+(function () {
+    angular.module('piwikApp').controller('SitesManagerSiteController', SitesManagerSiteController);
 
-angular.module('piwikApp').controller('SitesManagerSiteController', function ($scope, $filter, sitesManagerApiHelper) {
+    function SitesManagerSiteController($scope, $filter, sitesManagerApiHelper) {
 
-    var translate = $filter('translate');
+        var translate = $filter('translate');
 
-    var init = function () {
+        var init = function () {
 
-        initModel();
-        initActions();
-    };
+            initModel();
+            initActions();
+        };
 
-    var initActions = function () {
+        var initActions = function () {
 
-        $scope.editSite = editSite;
-        $scope.saveSite = saveSite;
-        $scope.openDeleteDialog = openDeleteDialog;
-        $scope.site.delete = deleteSite;
-    };
+            $scope.editSite = editSite;
+            $scope.saveSite = saveSite;
+            $scope.openDeleteDialog = openDeleteDialog;
+            $scope.site.delete = deleteSite;
+        };
 
-    var initModel = function() {
+        var initModel = function() {
 
-        if(siteIsNew())
-            initNewSite();
-        else
-            initExistingSite();
+            if(siteIsNew())
+                initNewSite();
+            else
+                initExistingSite();
 
-        $scope.site.editDialog = {};
-        $scope.site.removeDialog = {};
-    };
+            $scope.site.editDialog = {};
+            $scope.site.removeDialog = {};
+        };
 
-    var editSite = function () {
+        var editSite = function () {
 
-        if ($scope.siteIsBeingEdited) {
+            if ($scope.siteIsBeingEdited) {
 
-            $scope.site.editDialog.show = true;
-            $scope.site.editDialog.title = translate('SitesManager_OnlyOneSiteAtTime', '"' + $scope.lookupCurrentEditSite().name + '"');
+                $scope.site.editDialog.show = true;
+                $scope.site.editDialog.title = translate('SitesManager_OnlyOneSiteAtTime', '"' + $scope.lookupCurrentEditSite().name + '"');
 
-        } else {
+            } else {
 
-            $scope.site.editMode = true;
-            $scope.informSiteIsBeingEdited();
-        }
-    };
+                $scope.site.editMode = true;
+                $scope.informSiteIsBeingEdited();
+            }
+        };
+
+        var saveSite = function() {
+
+            var sendSiteSearchKeywordParams = $scope.site.sitesearch == '1' && !$scope.site.useDefaultSiteSearchParams;
+            var sendSearchCategoryParameters = sendSiteSearchKeywordParams && $scope.customVariablesActivated;
+
+            var ajaxHandler = new ajaxHelper();
+            ajaxHandler.addParams({
+                module: 'API',
+                format: 'json'
+            }, 'GET');
 
-    var saveSite = function() {
+            if(siteIsNew()) {
 
-        var sendSiteSearchKeywordParams = $scope.site.sitesearch == '1' && !$scope.site.useDefaultSiteSearchParams;
-        var sendSearchCategoryParameters = sendSiteSearchKeywordParams && $scope.customVariablesActivated;
+                ajaxHandler.addParams({
+                    method: 'SitesManager.addSite'
+                }, 'GET');
 
-        var ajaxHandler = new ajaxHelper();
-        ajaxHandler.addParams({
-            module: 'API',
-            format: 'json'
-        }, 'GET');
+            } else {
 
-        if(siteIsNew()) {
+                ajaxHandler.addParams({
+                    idSite: $scope.site.idsite,
+                    method: 'SitesManager.updateSite'
+                }, 'GET');
+            }
 
             ajaxHandler.addParams({
-                method: 'SitesManager.addSite'
-            }, 'GET');
+                siteName: $scope.site.name,
+                timezone: $scope.site.timezone,
+                currency: $scope.site.currency,
+                ecommerce: $scope.site.ecommerce,
+                excludedIps: $scope.site.excluded_ips.join(','),
+                excludedQueryParameters: $scope.site.excluded_parameters.join(','),
+                excludedUserAgents: $scope.site.excluded_user_agents.join(','),
+                keepURLFragments: $scope.site.keep_url_fragment,
+                siteSearch: $scope.site.sitesearch,
+                searchKeywordParameters: sendSiteSearchKeywordParams ? $scope.site.sitesearch_keyword_parameters.join(',') : null,
+                searchCategoryParameters: sendSearchCategoryParameters ? $scope.site.sitesearch_category_parameters.join(',') : null,
+                urls: $scope.site.alias_urls
+            }, 'POST');
+
+            ajaxHandler.redirectOnSuccess($scope.redirectParams);
+            ajaxHandler.setLoadingElement();
+            ajaxHandler.send(true);
+        };
+
+        var siteIsNew = function() {
+            return angular.isUndefined($scope.site.idsite);
+        };
+
+        var initNewSite = function() {
+
+            $scope.informSiteIsBeingEdited();
+
+            $scope.site.editMode = true;
+            $scope.site.name = "Name";
+            $scope.site.alias_urls = [
+                "http://siteUrl.com/",
+                "http://siteUrl2.com/"
+            ];
+            $scope.site.keep_url_fragment = "0";
+            $scope.site.excluded_ips = [];
+            $scope.site.excluded_parameters = [];
+            $scope.site.excluded_user_agents = [];
+            $scope.site.sitesearch_keyword_parameters = [];
+            $scope.site.sitesearch_category_parameters = [];
+            $scope.site.sitesearch = $scope.globalSettings.searchKeywordParametersGlobal.length ? "1" : "0";
+            $scope.site.timezone = $scope.globalSettings.defaultTimezone;
+            $scope.site.currency = $scope.globalSettings.defaultCurrency;
+            $scope.site.ecommerce = "0";
 
-        } else {
+            updateSiteWithSiteSearchConfig();
+        };
+
+        var initExistingSite = function() {
+
+            $scope.site.excluded_ips = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.site.excluded_ips);
+            $scope.site.excluded_parameters = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.site.excluded_parameters);
+            $scope.site.excluded_user_agents = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.site.excluded_user_agents);
+            $scope.site.sitesearch_keyword_parameters = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.site.sitesearch_keyword_parameters);
+            $scope.site.sitesearch_category_parameters = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.site.sitesearch_category_parameters);
+
+            updateSiteWithSiteSearchConfig();
+        };
+
+        var updateSiteWithSiteSearchConfig = function() {
+
+            $scope.site.useDefaultSiteSearchParams =
+                $scope.globalSettings.searchKeywordParametersGlobal.length && !$scope.site.sitesearch_keyword_parameters.length;
+        };
+
+        var openDeleteDialog = function() {
+
+            $scope.site.removeDialog.title = translate('SitesManager_DeleteConfirm', '"' + $scope.site.name + '" (idSite = ' + $scope.site.idsite + ')');
+            $scope.site.removeDialog.show = true;
+        };
+
+        var deleteSite = function() {
+
+            var ajaxHandler = new ajaxHelper();
 
             ajaxHandler.addParams({
                 idSite: $scope.site.idsite,
-                method: 'SitesManager.updateSite'
+                module: 'API',
+                format: 'json',
+                method: 'SitesManager.deleteSite'
             }, 'GET');
-        }
-
-        ajaxHandler.addParams({
-            siteName: $scope.site.name,
-            timezone: $scope.site.timezone,
-            currency: $scope.site.currency,
-            ecommerce: $scope.site.ecommerce,
-            excludedIps: $scope.site.excluded_ips.join(','),
-            excludedQueryParameters: $scope.site.excluded_parameters.join(','),
-            excludedUserAgents: $scope.site.excluded_user_agents.join(','),
-            keepURLFragments: $scope.site.keep_url_fragment,
-            siteSearch: $scope.site.sitesearch,
-            searchKeywordParameters: sendSiteSearchKeywordParams ? $scope.site.sitesearch_keyword_parameters.join(',') : null,
-            searchCategoryParameters: sendSearchCategoryParameters ? $scope.site.sitesearch_category_parameters.join(',') : null,
-            urls: $scope.site.alias_urls
-        }, 'POST');
-
-        ajaxHandler.redirectOnSuccess($scope.redirectParams);
-        ajaxHandler.setLoadingElement();
-        ajaxHandler.send(true);
-    };
-
-    var siteIsNew = function() {
-        return angular.isUndefined($scope.site.idsite);
-    };
-
-    var initNewSite = function() {
-
-        $scope.informSiteIsBeingEdited();
-
-        $scope.site.editMode = true;
-        $scope.site.name = "Name";
-        $scope.site.alias_urls = [
-            "http://siteUrl.com/",
-            "http://siteUrl2.com/"
-        ];
-        $scope.site.keep_url_fragment = "0";
-        $scope.site.excluded_ips = [];
-        $scope.site.excluded_parameters = [];
-        $scope.site.excluded_user_agents = [];
-        $scope.site.sitesearch_keyword_parameters = [];
-        $scope.site.sitesearch_category_parameters = [];
-        $scope.site.sitesearch = $scope.globalSettings.searchKeywordParametersGlobal.length ? "1" : "0";
-        $scope.site.timezone = $scope.globalSettings.defaultTimezone;
-        $scope.site.currency = $scope.globalSettings.defaultCurrency;
-        $scope.site.ecommerce = "0";
-
-        updateSiteWithSiteSearchConfig();
-    };
-
-    var initExistingSite = function() {
-
-        $scope.site.excluded_ips = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.site.excluded_ips);
-        $scope.site.excluded_parameters = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.site.excluded_parameters);
-        $scope.site.excluded_user_agents = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.site.excluded_user_agents);
-        $scope.site.sitesearch_keyword_parameters = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.site.sitesearch_keyword_parameters);
-        $scope.site.sitesearch_category_parameters = sitesManagerApiHelper.commaDelimitedFieldToArray($scope.site.sitesearch_category_parameters);
-
-        updateSiteWithSiteSearchConfig();
-    };
-
-    var updateSiteWithSiteSearchConfig = function() {
-
-        $scope.site.useDefaultSiteSearchParams =
-            $scope.globalSettings.searchKeywordParametersGlobal.length && !$scope.site.sitesearch_keyword_parameters.length;
-    };
-
-    var openDeleteDialog = function() {
-
-        $scope.site.removeDialog.title = translate('SitesManager_DeleteConfirm', '"' + $scope.site.name + '" (idSite = ' + $scope.site.idsite + ')');
-        $scope.site.removeDialog.show = true;
-    };
-
-    var deleteSite = function() {
-
-        var ajaxHandler = new ajaxHelper();
-
-        ajaxHandler.addParams({
-            idSite: $scope.site.idsite,
-            module: 'API',
-            format: 'json',
-            method: 'SitesManager.deleteSite'
-        }, 'GET');
-
-        ajaxHandler.redirectOnSuccess($scope.redirectParams);
-        ajaxHandler.setLoadingElement();
-        ajaxHandler.send(true);
-    };
-
-    init();
-});
+
+            ajaxHandler.redirectOnSuccess($scope.redirectParams);
+            ajaxHandler.setLoadingElement();
+            ajaxHandler.send(true);
+        };
+
+        init();
+    }
+})();
\ No newline at end of file
diff --git a/plugins/ZenMode/angularjs/quick-access/quick-access-directive.js b/plugins/ZenMode/angularjs/quick-access/quick-access-directive.js
index fe1b196602..fa5553bf49 100644
--- a/plugins/ZenMode/angularjs/quick-access/quick-access-directive.js
+++ b/plugins/ZenMode/angularjs/quick-access/quick-access-directive.js
@@ -12,123 +12,127 @@
  *
  * Will execute the "executeMyFunction" function in the current scope once the yes button is pressed.
  */
-angular.module('piwikApp').directive('piwikQuickAccess', function($rootElement, $timeout, $filter, siteSelectorModel, piwik) {
-
-    return {
-        restrict: 'A',
-        replace: true,
-        scope: {},
-        templateUrl: 'plugins/ZenMode/angularjs/quick-access/quick-access.html?cb=' + piwik.cacheBuster,
-        link: function (scope, element, attrs) {
-
-            var menuIndex = -1;
-            var menuItems = [];
-            var reportEntries = [];
-
-            scope.reportEntries = [];
-            scope.menuItems  = [];
-            scope.sitesModel = siteSelectorModel;
-
-            function getMenuItems()
-            {
-                if (menuItems && menuItems.length) {
+(function () {
+    angular.module('piwikApp').directive('piwikQuickAccess', QuickAccessDirective);
+
+    function QuickAccessDirective ($rootElement, $timeout, $filter, siteSelectorModel, piwik) {
+
+        return {
+            restrict: 'A',
+            replace: true,
+            scope: {},
+            templateUrl: 'plugins/ZenMode/angularjs/quick-access/quick-access.html?cb=' + piwik.cacheBuster,
+            link: function (scope, element, attrs) {
+
+                var menuIndex = -1;
+                var menuItems = [];
+                var reportEntries = [];
+
+                scope.reportEntries = [];
+                scope.menuItems  = [];
+                scope.sitesModel = siteSelectorModel;
+
+                function getMenuItems()
+                {
+                    if (menuItems && menuItems.length) {
+                        return menuItems;
+                    }
+
+                    $rootElement.find('#topRightBar .topBarElem a').each(function (index, element) {
+                        menuItems.push({name: $(element).text(), index: ++menuIndex, category: 'menuCategory'});
+                        $(element).attr('quick_access', menuIndex);
+                    });
+
                     return menuItems;
                 }
 
-                $rootElement.find('#topRightBar .topBarElem a').each(function (index, element) {
-                    menuItems.push({name: $(element).text(), index: ++menuIndex, category: 'menuCategory'});
-                    $(element).attr('quick_access', menuIndex);
-                });
+                function getReportEntries()
+                {
+                    if (reportEntries && reportEntries.length) {
+                        return reportEntries;
+                    }
 
-                return menuItems;
-            }
+                    $rootElement.find('.Menu-tabList a').each(function (index, element) {
+                        reportEntries.push({name: $(element).text(), category: 'reportCategory', index: ++menuIndex});
+                        $(element).attr('quick_access', menuIndex);
+                    });
 
-            function getReportEntries()
-            {
-                if (reportEntries && reportEntries.length) {
                     return reportEntries;
                 }
 
-                $rootElement.find('.Menu-tabList a').each(function (index, element) {
-                    reportEntries.push({name: $(element).text(), category: 'reportCategory', index: ++menuIndex});
-                    $(element).attr('quick_access', menuIndex);
-                });
-
-                return reportEntries;
-            }
-
-            function highlightPreviousItem()
-            {
-                if (0 >= (scope.search.index - 1)) {
-                    scope.search.index = 0;
-                } else {
-                    scope.search.index--;
+                function highlightPreviousItem()
+                {
+                    if (0 >= (scope.search.index - 1)) {
+                        scope.search.index = 0;
+                    } else {
+                        scope.search.index--;
+                    }
                 }
-            }
 
-            function highlightNextItem()
-            {
-                var numTotal = element.find('li.result').length;
+                function highlightNextItem()
+                {
+                    var numTotal = element.find('li.result').length;
 
-                if (numTotal <= (scope.search.index + 1)) {
-                    scope.search.index = numTotal - 1;
-                } else {
-                    scope.search.index++;
+                    if (numTotal <= (scope.search.index + 1)) {
+                        scope.search.index = numTotal - 1;
+                    } else {
+                        scope.search.index++;
+                    }
                 }
-            }
 
-            function executeMenuItem()
-            {
-                var results = element.find('li.result');
-                if (results && results.length && results[scope.search.index]) {
-                    var selectedMenuElement = $(results[scope.search.index]);
-                    $timeout(function () {
-                        selectedMenuElement.click();
-                    }, 20);
+                function executeMenuItem()
+                {
+                    var results = element.find('li.result');
+                    if (results && results.length && results[scope.search.index]) {
+                        var selectedMenuElement = $(results[scope.search.index]);
+                        $timeout(function () {
+                            selectedMenuElement.click();
+                        }, 20);
+                    }
                 }
-            }
 
-            scope.onKeypress = function (event) {
+                scope.onKeypress = function (event) {
 
-                if (38 == event.which) {
-                    highlightPreviousItem();
-                    event.preventDefault();
-                } else if (40 == event.which) {
-                    highlightNextItem();
-                    event.preventDefault();
-                } else if (13 == event.which) {
-                    executeMenuItem();
-                }
-            };
+                    if (38 == event.which) {
+                        highlightPreviousItem();
+                        event.preventDefault();
+                    } else if (40 == event.which) {
+                        highlightNextItem();
+                        event.preventDefault();
+                    } else if (13 == event.which) {
+                        executeMenuItem();
+                    }
+                };
 
-            scope.search = function (searchTerm) {
-                this.search.index  = 0;
+                scope.search = function (searchTerm) {
+                    this.search.index  = 0;
 
-                this.menuItems     = $filter('filter')(getMenuItems(), searchTerm);
-                this.reportEntries = $filter('filter')(getReportEntries(), searchTerm);
-                this.sitesModel.searchSite(searchTerm);
-            };
+                    this.menuItems     = $filter('filter')(getMenuItems(), searchTerm);
+                    this.reportEntries = $filter('filter')(getReportEntries(), searchTerm);
+                    this.sitesModel.searchSite(searchTerm);
+                };
 
-            scope.selectSite = function (idsite) {
-                this.sitesModel.loadSite(idsite);
-            };
+                scope.selectSite = function (idsite) {
+                    this.sitesModel.loadSite(idsite);
+                };
 
-            scope.selectMenuItem = function (index) {
-                var target = $rootElement.find('[quick_access=' + index + ']');
+                scope.selectMenuItem = function (index) {
+                    var target = $rootElement.find('[quick_access=' + index + ']');
 
-                if (target && target.length && target[0]) {
-                    var actualTarget = target[0];
+                    if (target && target.length && target[0]) {
+                        var actualTarget = target[0];
 
-                    var href = $(actualTarget).attr('href');
+                        var href = $(actualTarget).attr('href');
 
-                    if (href && href.length > 10) {
-                        actualTarget.click();
-                    } else {
-                        $(actualTarget).click();
+                        if (href && href.length > 10) {
+                            actualTarget.click();
+                        } else {
+                            $(actualTarget).click();
+                        }
                     }
-                }
-            };
+                };
 
-        }
-    };
-});
\ No newline at end of file
+            }
+        };
+    }
+})();
\ No newline at end of file
diff --git a/plugins/ZenMode/angularjs/zen-mode/zen-mode-switcher-directive.js b/plugins/ZenMode/angularjs/zen-mode/zen-mode-switcher-directive.js
index 6a54ef446e..12a1a8e3fa 100644
--- a/plugins/ZenMode/angularjs/zen-mode/zen-mode-switcher-directive.js
+++ b/plugins/ZenMode/angularjs/zen-mode/zen-mode-switcher-directive.js
@@ -10,39 +10,43 @@
  * <div piwik-zen-mode-switcher>...</div>
  * Will toggle the zen mode on click on this element.
  */
-angular.module('piwikApp').directive('piwikZenModeSwitcher', function($rootElement, $filter) {
-
-    function showZenModeIsActivatedNotification() {
-        var howToSearch = $filter('translate')('ZenMode_HowToSearch');
-        var howToToggle = $filter('translate')('ZenMode_HowToToggleZenMode');
-        var activated   = $filter('translate')('ZenMode_Activated');
-
-        var message = '<ul><li>' + howToSearch + '</li><li>' + howToToggle + '</li></ul>';
-
-        var UI = require('piwik/UI');
-        var notification = new UI.Notification();
-        notification.show(message, {
-            title: activated,
-            context: 'info',
-            id: 'ZenMode_EnabledInfo'
-        });
-    }
+(function () {
+    angular.module('piwikApp').directive('piwikZenModeSwitcher', piwikZenModeSwitcher);
 
-    return {
-        restrict: 'A',
-        compile: function (element, attrs) {
+    function piwikZenModeSwitcher($rootElement, $filter) {
 
-            element.on('click', function() {
-                $rootElement.trigger('zen-mode-toggle', {});
+        function showZenModeIsActivatedNotification() {
+            var howToSearch = $filter('translate')('ZenMode_HowToSearch');
+            var howToToggle = $filter('translate')('ZenMode_HowToToggleZenMode');
+            var activated   = $filter('translate')('ZenMode_Activated');
 
-                if ($rootElement.hasClass('zenMode')) {
-                    showZenModeIsActivatedNotification();
-                }
-            });
+            var message = '<ul><li>' + howToSearch + '</li><li>' + howToToggle + '</li></ul>';
 
-            return function () {
-            };
+            var UI = require('piwik/UI');
+            var notification = new UI.Notification();
+            notification.show(message, {
+                title: activated,
+                context: 'info',
+                id: 'ZenMode_EnabledInfo'
+            });
         }
-    };
 
-});
\ No newline at end of file
+        return {
+            restrict: 'A',
+            compile: function (element, attrs) {
+
+                element.on('click', function() {
+                    $rootElement.trigger('zen-mode-toggle', {});
+
+                    if ($rootElement.hasClass('zenMode')) {
+                        showZenModeIsActivatedNotification();
+                    }
+                });
+
+                return function () {
+                };
+            }
+        };
+
+    }
+})();
\ No newline at end of file
-- 
GitLab