/** * Directives which show, hide, include or otherwise mutate the DOM based on Features and Config. */ /** * Adds a quay-require attribute includes an element in the DOM iff the features specified are true. */ angular.module('quay').directive('quayRequire', function ($animate, Features, AngularHelper) { return { transclude: 'element', priority: 600, terminal: true, restrict: 'A', link: AngularHelper.buildConditionalLinker($animate, 'quayRequire', function(value) { return Features.matchesFeatures(value); }) }; }); /** * Adds a quay-show attribute that shows the element only if the attribute evaluates to true. * The Features and Config services are added into the scope's context automatically. */ angular.module('quay').directive('quayShow', function($animate, Features, Config) { return { priority: 590, restrict: 'A', link: function($scope, $element, $attr, ctrl, $transclude) { $scope.Features = Features; $scope.Config = Config; $scope.$watch($attr.quayShow, function(result) { $animate[!!result ? 'removeClass' : 'addClass']($element, 'ng-hide'); }); } }; }); /** * Adds a quay-section attribute that adds an 'active' class to the element if the current URL * matches the given section. */ angular.module('quay').directive('quaySection', function($animate, $location, $rootScope) { return { priority: 590, restrict: 'A', link: function($scope, $element, $attr, ctrl, $transclude) { var update = function() { var result = $location.path().indexOf('/' + $attr.quaySection) == 0; $animate[!result ? 'removeClass' : 'addClass']($element, 'active'); }; $scope.$watch(function(){ return $location.path(); }, update); $scope.$watch($attr.quaySection, update); } }; }); /** * Adds a quay-classes attribute that performs like ng-class, but with Features and Config also * available in the scope automatically. */ angular.module('quay').directive('quayClasses', function(Features, Config) { return { priority: 580, restrict: 'A', link: function($scope, $element, $attr, ctrl, $transclude) { // Borrowed from ngClass. function flattenClasses(classVal) { if(angular.isArray(classVal)) { return classVal.join(' '); } else if (angular.isObject(classVal)) { var classes = [], i = 0; angular.forEach(classVal, function(v, k) { if (v) { classes.push(k); } }); return classes.join(' '); } return classVal; } function removeClass(classVal) { $attr.$removeClass(flattenClasses(classVal)); } function addClass(classVal) { $attr.$addClass(flattenClasses(classVal)); } $scope.$watch($attr.quayClasses, function(result) { var scopeVals = { 'Features': Features, 'Config': Config }; for (var expr in result) { if (!result.hasOwnProperty(expr)) { continue; } // Evaluate the expression with the entire features list added. var value = $scope.$eval(expr, scopeVals); if (value) { addClass(result[expr]); } else { removeClass(result[expr]); } } }); } }; }); /** * Adds a quay-include attribtue that adds a template solely if the expression evaluates to true. * Automatically adds the Features and Config services to the scope. * Usage: quay-include="{'Features.BILLING': 'partials/landing-normal.html', '!Features.BILLING': 'partials/landing-login.html'}" */ angular.module('quay').directive('quayInclude', function($compile, $templateCache, $http, Features, Config) { return { priority: 595, restrict: 'A', link: function($scope, $element, $attr, ctrl) { var getTemplate = function(templateName) { var templateUrl = '/static/' + templateName; return $http.get(templateUrl, {cache: $templateCache}); }; var result = $scope.$eval($attr.quayInclude); if (!result) { return; } var scopeVals = { 'Features': Features, 'Config': Config }; var templatePath = null; for (var expr in result) { if (!result.hasOwnProperty(expr)) { continue; } // Evaluate the expression with the entire features list added. var value = $scope.$eval(expr, scopeVals); if (value) { templatePath = result[expr]; break; } } if (!templatePath) { return; } var promise = getTemplate(templatePath).success(function(html) { $element.html(html); }).then(function (response) { $element.replaceWith($compile($element.html())($scope)); if ($attr.onload) { $scope.$eval($attr.onload); } }); } }; });