UNPKG

thalassa-crowsnest

Version:
142 lines (123 loc) 4.91 kB
angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse']) .constant('accordionConfig', { closeOthers: true }) .controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) { // This array keeps track of the accordion groups this.groups = []; // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to this.closeOthers = function(openGroup) { var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers; if ( closeOthers ) { angular.forEach(this.groups, function (group) { if ( group !== openGroup ) { group.isOpen = false; } }); } }; // This is called from the accordion-group directive to add itself to the accordion this.addGroup = function(groupScope) { var that = this; this.groups.push(groupScope); groupScope.$on('$destroy', function (event) { that.removeGroup(groupScope); }); }; // This is called from the accordion-group directive when to remove itself this.removeGroup = function(group) { var index = this.groups.indexOf(group); if ( index !== -1 ) { this.groups.splice(this.groups.indexOf(group), 1); } }; }]) // The accordion directive simply sets up the directive controller // and adds an accordion CSS class to itself element. .directive('accordion', function () { return { restrict:'EA', controller:'AccordionController', transclude: true, replace: false, templateUrl: 'template/accordion/accordion.html' }; }) // The accordion-group directive indicates a block of html that will expand and collapse in an accordion .directive('accordionGroup', ['$parse', '$transition', '$timeout', function($parse, $transition, $timeout) { return { require:'^accordion', // We need this directive to be inside an accordion restrict:'EA', transclude:true, // It transcludes the contents of the directive into the template replace: true, // The element containing the directive will be replaced with the template templateUrl:'template/accordion/accordion-group.html', scope:{ heading:'@' }, // Create an isolated scope and interpolate the heading attribute onto this scope controller: ['$scope', function($scope) { this.setHeading = function(element) { this.heading = element; }; }], link: function(scope, element, attrs, accordionCtrl) { var getIsOpen, setIsOpen; accordionCtrl.addGroup(scope); scope.isOpen = false; if ( attrs.isOpen ) { getIsOpen = $parse(attrs.isOpen); setIsOpen = getIsOpen.assign; scope.$watch( function watchIsOpen() { return getIsOpen(scope.$parent); }, function updateOpen(value) { scope.isOpen = value; } ); scope.isOpen = getIsOpen ? getIsOpen(scope.$parent) : false; } scope.$watch('isOpen', function(value) { if ( value ) { accordionCtrl.closeOthers(scope); } if ( setIsOpen ) { setIsOpen(scope.$parent, value); } }); } }; }]) // Use accordion-heading below an accordion-group to provide a heading containing HTML // <accordion-group> // <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading> // </accordion-group> .directive('accordionHeading', function() { return { restrict: 'EA', transclude: true, // Grab the contents to be used as the heading template: '', // In effect remove this element! replace: true, require: '^accordionGroup', compile: function(element, attr, transclude) { return function link(scope, element, attr, accordionGroupCtrl) { // Pass the heading to the accordion-group controller // so that it can be transcluded into the right place in the template // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat] accordionGroupCtrl.setHeading(transclude(scope, function() {})); }; } }; }) // Use in the accordion-group template to indicate where you want the heading to be transcluded // You must provide the property on the accordion-group controller that will hold the transcluded element // <div class="accordion-group"> // <div class="accordion-heading" ><a ... accordion-transclude="heading">...</a></div> // ... // </div> .directive('accordionTransclude', function() { return { require: '^accordionGroup', link: function(scope, element, attr, controller) { scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) { if ( heading ) { element.html(''); element.append(heading); } }); } }; });