tab.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /**
  2. * angular-strap
  3. * @version v2.3.9 - 2016-06-10
  4. * @link http://mgcrea.github.io/angular-strap
  5. * @author Olivier Louvignes <olivier@mg-crea.com> (https://github.com/mgcrea)
  6. * @license MIT License, http://www.opensource.org/licenses/MIT
  7. */
  8. 'use strict';
  9. angular.module('mgcrea.ngStrap.tab', []).provider('$tab', function() {
  10. var defaults = this.defaults = {
  11. animation: 'am-fade',
  12. template: 'tab/tab.tpl.html',
  13. navClass: 'nav-tabs',
  14. activeClass: 'active'
  15. };
  16. var controller = this.controller = function($scope, $element, $attrs) {
  17. var self = this;
  18. self.$options = angular.copy(defaults);
  19. angular.forEach([ 'animation', 'navClass', 'activeClass' ], function(key) {
  20. if (angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];
  21. });
  22. $scope.$navClass = self.$options.navClass;
  23. $scope.$activeClass = self.$options.activeClass;
  24. self.$panes = $scope.$panes = [];
  25. self.$activePaneChangeListeners = self.$viewChangeListeners = [];
  26. self.$push = function(pane) {
  27. if (angular.isUndefined(self.$panes.$active)) {
  28. $scope.$setActive(pane.name || 0);
  29. }
  30. self.$panes.push(pane);
  31. };
  32. self.$remove = function(pane) {
  33. var index = self.$panes.indexOf(pane);
  34. var active = self.$panes.$active;
  35. var activeIndex;
  36. if (angular.isString(active)) {
  37. activeIndex = self.$panes.map(function(pane) {
  38. return pane.name;
  39. }).indexOf(active);
  40. } else {
  41. activeIndex = self.$panes.$active;
  42. }
  43. self.$panes.splice(index, 1);
  44. if (index < activeIndex) {
  45. activeIndex--;
  46. } else if (index === activeIndex && activeIndex === self.$panes.length) {
  47. activeIndex--;
  48. }
  49. if (activeIndex >= 0 && activeIndex < self.$panes.length) {
  50. self.$setActive(self.$panes[activeIndex].name || activeIndex);
  51. } else {
  52. self.$setActive();
  53. }
  54. };
  55. self.$setActive = $scope.$setActive = function(value) {
  56. self.$panes.$active = value;
  57. self.$activePaneChangeListeners.forEach(function(fn) {
  58. fn();
  59. });
  60. };
  61. self.$isActive = $scope.$isActive = function($pane, $index) {
  62. return self.$panes.$active === $pane.name || self.$panes.$active === $index;
  63. };
  64. };
  65. this.$get = function() {
  66. var $tab = {};
  67. $tab.defaults = defaults;
  68. $tab.controller = controller;
  69. return $tab;
  70. };
  71. }).directive('bsTabs', [ '$window', '$animate', '$tab', '$parse', function($window, $animate, $tab, $parse) {
  72. var defaults = $tab.defaults;
  73. return {
  74. require: [ '?ngModel', 'bsTabs' ],
  75. transclude: true,
  76. scope: true,
  77. controller: [ '$scope', '$element', '$attrs', $tab.controller ],
  78. templateUrl: function(element, attr) {
  79. return attr.template || defaults.template;
  80. },
  81. link: function postLink(scope, element, attrs, controllers) {
  82. var ngModelCtrl = controllers[0];
  83. var bsTabsCtrl = controllers[1];
  84. if (ngModelCtrl) {
  85. bsTabsCtrl.$activePaneChangeListeners.push(function() {
  86. ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);
  87. });
  88. ngModelCtrl.$formatters.push(function(modelValue) {
  89. bsTabsCtrl.$setActive(modelValue);
  90. return modelValue;
  91. });
  92. }
  93. if (attrs.bsActivePane) {
  94. var parsedBsActivePane = $parse(attrs.bsActivePane);
  95. bsTabsCtrl.$activePaneChangeListeners.push(function() {
  96. parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);
  97. });
  98. scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {
  99. bsTabsCtrl.$setActive(newValue);
  100. }, true);
  101. }
  102. }
  103. };
  104. } ]).directive('bsPane', [ '$window', '$animate', '$sce', function($window, $animate, $sce) {
  105. return {
  106. require: [ '^?ngModel', '^bsTabs' ],
  107. scope: true,
  108. link: function postLink(scope, element, attrs, controllers) {
  109. var bsTabsCtrl = controllers[1];
  110. element.addClass('tab-pane');
  111. attrs.$observe('title', function(newValue, oldValue) {
  112. scope.title = $sce.trustAsHtml(newValue);
  113. });
  114. scope.name = attrs.name;
  115. if (bsTabsCtrl.$options.animation) {
  116. element.addClass(bsTabsCtrl.$options.animation);
  117. }
  118. attrs.$observe('disabled', function(newValue, oldValue) {
  119. scope.disabled = scope.$eval(newValue);
  120. });
  121. bsTabsCtrl.$push(scope);
  122. scope.$on('$destroy', function() {
  123. bsTabsCtrl.$remove(scope);
  124. });
  125. function render() {
  126. var index = bsTabsCtrl.$panes.indexOf(scope);
  127. $animate[bsTabsCtrl.$isActive(scope, index) ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);
  128. }
  129. bsTabsCtrl.$activePaneChangeListeners.push(function() {
  130. render();
  131. });
  132. render();
  133. }
  134. };
  135. } ]);