angular-strap-rails 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.gitignore +17 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +45 -0
  7. data/Rakefile +1 -0
  8. data/angular-strap-rails.gemspec +15 -0
  9. data/lib/angular-strap-rails.rb +8 -0
  10. data/lib/angular-strap-rails/version.rb +5 -0
  11. data/vendor/.DS_Store +0 -0
  12. data/vendor/assets/.DS_Store +0 -0
  13. data/vendor/assets/javascripts/.DS_Store +0 -0
  14. data/vendor/assets/javascripts/angular-strap.coffee +0 -0
  15. data/vendor/assets/javascripts/angular-strap/.DS_Store +0 -0
  16. data/vendor/assets/javascripts/angular-strap/datepicker.coffee +11 -0
  17. data/vendor/assets/javascripts/angular-strap/modal.coffee +9 -0
  18. data/vendor/assets/javascripts/dist/angular-strap.js +3682 -0
  19. data/vendor/assets/javascripts/dist/angular-strap.tpl.js +100 -0
  20. data/vendor/assets/javascripts/dist/modules/affix.js +191 -0
  21. data/vendor/assets/javascripts/dist/modules/alert.js +114 -0
  22. data/vendor/assets/javascripts/dist/modules/alert.tpl.js +14 -0
  23. data/vendor/assets/javascripts/dist/modules/aside.js +96 -0
  24. data/vendor/assets/javascripts/dist/modules/aside.tpl.js +14 -0
  25. data/vendor/assets/javascripts/dist/modules/button.js +141 -0
  26. data/vendor/assets/javascripts/dist/modules/date-parser.js +150 -0
  27. data/vendor/assets/javascripts/dist/modules/datepicker.js +583 -0
  28. data/vendor/assets/javascripts/dist/modules/datepicker.tpl.js +14 -0
  29. data/vendor/assets/javascripts/dist/modules/debounce.js +60 -0
  30. data/vendor/assets/javascripts/dist/modules/dimensions.js +142 -0
  31. data/vendor/assets/javascripts/dist/modules/dropdown.js +124 -0
  32. data/vendor/assets/javascripts/dist/modules/dropdown.tpl.js +14 -0
  33. data/vendor/assets/javascripts/dist/modules/modal.js +282 -0
  34. data/vendor/assets/javascripts/dist/modules/modal.tpl.js +14 -0
  35. data/vendor/assets/javascripts/dist/modules/navbar.js +55 -0
  36. data/vendor/assets/javascripts/dist/modules/parse-options.js +51 -0
  37. data/vendor/assets/javascripts/dist/modules/popover.js +100 -0
  38. data/vendor/assets/javascripts/dist/modules/popover.tpl.js +14 -0
  39. data/vendor/assets/javascripts/dist/modules/raf.js +45 -0
  40. data/vendor/assets/javascripts/dist/modules/scrollspy.js +229 -0
  41. data/vendor/assets/javascripts/dist/modules/select.js +281 -0
  42. data/vendor/assets/javascripts/dist/modules/select.tpl.js +14 -0
  43. data/vendor/assets/javascripts/dist/modules/tab.js +69 -0
  44. data/vendor/assets/javascripts/dist/modules/tab.tpl.js +14 -0
  45. data/vendor/assets/javascripts/dist/modules/timepicker.js +430 -0
  46. data/vendor/assets/javascripts/dist/modules/timepicker.tpl.js +14 -0
  47. data/vendor/assets/javascripts/dist/modules/tooltip.js +405 -0
  48. data/vendor/assets/javascripts/dist/modules/tooltip.tpl.js +14 -0
  49. data/vendor/assets/javascripts/dist/modules/typeahead.js +225 -0
  50. data/vendor/assets/javascripts/dist/modules/typeahead.tpl.js +14 -0
  51. data/vendor/assets/stylesheets/angular-strap.css +564 -0
  52. metadata +94 -0
@@ -0,0 +1,14 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.0.1 - 2014-04-10
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ 'use strict';
9
+ angular.module('mgcrea.ngStrap.modal').run([
10
+ '$templateCache',
11
+ function ($templateCache) {
12
+ $templateCache.put('modal/modal.tpl.html', '<div class="modal" tabindex="-1" role="dialog"><div class="modal-dialog"><div class="modal-content"><div class="modal-header" ng-show="title"><button type="button" class="close" ng-click="$hide()">&times;</button><h4 class="modal-title" ng-bind="title"></h4></div><div class="modal-body" ng-bind="content"></div><div class="modal-footer"><button type="button" class="btn btn-default" ng-click="$hide()">Close</button></div></div></div></div>');
13
+ }
14
+ ]);
@@ -0,0 +1,55 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.0.1 - 2014-04-10
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ 'use strict';
9
+ angular.module('mgcrea.ngStrap.navbar', []).provider('$navbar', function () {
10
+ var defaults = this.defaults = {
11
+ activeClass: 'active',
12
+ routeAttr: 'data-match-route',
13
+ strict: false
14
+ };
15
+ this.$get = function () {
16
+ return { defaults: defaults };
17
+ };
18
+ }).directive('bsNavbar', [
19
+ '$window',
20
+ '$location',
21
+ '$navbar',
22
+ function ($window, $location, $navbar) {
23
+ var defaults = $navbar.defaults;
24
+ return {
25
+ restrict: 'A',
26
+ link: function postLink(scope, element, attr, controller) {
27
+ // Directive options
28
+ var options = angular.copy(defaults);
29
+ angular.forEach(Object.keys(defaults), function (key) {
30
+ if (angular.isDefined(attr[key]))
31
+ options[key] = attr[key];
32
+ });
33
+ // Watch for the $location
34
+ scope.$watch(function () {
35
+ return $location.path();
36
+ }, function (newValue, oldValue) {
37
+ var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');
38
+ angular.forEach(liElements, function (li) {
39
+ var liElement = angular.element(li);
40
+ var pattern = liElement.attr(options.routeAttr).replace('/', '\\/');
41
+ if (options.strict) {
42
+ pattern = '^' + pattern + '$';
43
+ }
44
+ var regexp = new RegExp(pattern, ['i']);
45
+ if (regexp.test(newValue)) {
46
+ liElement.addClass(options.activeClass);
47
+ } else {
48
+ liElement.removeClass(options.activeClass);
49
+ }
50
+ });
51
+ });
52
+ }
53
+ };
54
+ }
55
+ ]);
@@ -0,0 +1,51 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.0.1 - 2014-04-10
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ 'use strict';
9
+ angular.module('mgcrea.ngStrap.helpers.parseOptions', []).provider('$parseOptions', function () {
10
+ var defaults = this.defaults = { regexp: /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/ };
11
+ this.$get = [
12
+ '$parse',
13
+ '$q',
14
+ function ($parse, $q) {
15
+ function ParseOptionsFactory(attr, config) {
16
+ var $parseOptions = {};
17
+ // Common vars
18
+ var options = angular.extend({}, defaults, config);
19
+ $parseOptions.$values = [];
20
+ // Private vars
21
+ var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;
22
+ $parseOptions.init = function () {
23
+ $parseOptions.$match = match = attr.match(options.regexp);
24
+ displayFn = $parse(match[2] || match[1]), valueName = match[4] || match[6], keyName = match[5], groupByFn = $parse(match[3] || ''), valueFn = $parse(match[2] ? match[1] : valueName), valuesFn = $parse(match[7]);
25
+ };
26
+ $parseOptions.valuesFn = function (scope, controller) {
27
+ return $q.when(valuesFn(scope, controller)).then(function (values) {
28
+ $parseOptions.$values = values ? parseValues(values) : {};
29
+ return $parseOptions.$values;
30
+ });
31
+ };
32
+ // Private functions
33
+ function parseValues(values) {
34
+ return values.map(function (match, index) {
35
+ var locals = {}, label, value;
36
+ locals[valueName] = match;
37
+ label = displayFn(locals);
38
+ value = valueFn(locals) || index;
39
+ return {
40
+ label: label,
41
+ value: value
42
+ };
43
+ });
44
+ }
45
+ $parseOptions.init();
46
+ return $parseOptions;
47
+ }
48
+ return ParseOptionsFactory;
49
+ }
50
+ ];
51
+ });
@@ -0,0 +1,100 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.0.1 - 2014-04-10
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ 'use strict';
9
+ angular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip']).provider('$popover', function () {
10
+ var defaults = this.defaults = {
11
+ animation: 'am-fade',
12
+ placement: 'right',
13
+ template: 'popover/popover.tpl.html',
14
+ contentTemplate: false,
15
+ trigger: 'click',
16
+ keyboard: true,
17
+ html: false,
18
+ title: '',
19
+ content: '',
20
+ delay: 0,
21
+ container: false
22
+ };
23
+ this.$get = [
24
+ '$tooltip',
25
+ function ($tooltip) {
26
+ function PopoverFactory(element, config) {
27
+ // Common vars
28
+ var options = angular.extend({}, defaults, config);
29
+ var $popover = $tooltip(element, options);
30
+ // Support scope as string options [/*title, */content]
31
+ if (options.content) {
32
+ $popover.$scope.content = options.content;
33
+ }
34
+ return $popover;
35
+ }
36
+ return PopoverFactory;
37
+ }
38
+ ];
39
+ }).directive('bsPopover', [
40
+ '$window',
41
+ '$location',
42
+ '$sce',
43
+ '$popover',
44
+ function ($window, $location, $sce, $popover) {
45
+ var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;
46
+ return {
47
+ restrict: 'EAC',
48
+ scope: true,
49
+ link: function postLink(scope, element, attr) {
50
+ // Directive options
51
+ var options = { scope: scope };
52
+ angular.forEach([
53
+ 'template',
54
+ 'contentTemplate',
55
+ 'placement',
56
+ 'container',
57
+ 'delay',
58
+ 'trigger',
59
+ 'keyboard',
60
+ 'html',
61
+ 'animation'
62
+ ], function (key) {
63
+ if (angular.isDefined(attr[key]))
64
+ options[key] = attr[key];
65
+ });
66
+ // Support scope as data-attrs
67
+ angular.forEach([
68
+ 'title',
69
+ 'content'
70
+ ], function (key) {
71
+ attr[key] && attr.$observe(key, function (newValue, oldValue) {
72
+ scope[key] = $sce.trustAsHtml(newValue);
73
+ angular.isDefined(oldValue) && requestAnimationFrame(function () {
74
+ popover && popover.$applyPlacement();
75
+ });
76
+ });
77
+ });
78
+ // Support scope as an object
79
+ attr.bsPopover && scope.$watch(attr.bsPopover, function (newValue, oldValue) {
80
+ if (angular.isObject(newValue)) {
81
+ angular.extend(scope, newValue);
82
+ } else {
83
+ scope.content = newValue;
84
+ }
85
+ angular.isDefined(oldValue) && requestAnimationFrame(function () {
86
+ popover && popover.$applyPlacement();
87
+ });
88
+ }, true);
89
+ // Initialize popover
90
+ var popover = $popover(element, options);
91
+ // Garbage collection
92
+ scope.$on('$destroy', function () {
93
+ popover.destroy();
94
+ options = null;
95
+ popover = null;
96
+ });
97
+ }
98
+ };
99
+ }
100
+ ]);
@@ -0,0 +1,14 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.0.1 - 2014-04-10
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ 'use strict';
9
+ angular.module('mgcrea.ngStrap.popover').run([
10
+ '$templateCache',
11
+ function ($templateCache) {
12
+ $templateCache.put('popover/popover.tpl.html', '<div class="popover"><div class="arrow"></div><h3 class="popover-title" ng-bind="title" ng-show="title"></h3><div class="popover-content" ng-bind="content"></div></div>');
13
+ }
14
+ ]);
@@ -0,0 +1,45 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.0.1 - 2014-04-10
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ 'use strict';
9
+ angular.version.minor < 3 && angular.version.dot < 14 && angular.module('ng').factory('$$rAF', [
10
+ '$window',
11
+ '$timeout',
12
+ function ($window, $timeout) {
13
+ var requestAnimationFrame = $window.requestAnimationFrame || $window.webkitRequestAnimationFrame || $window.mozRequestAnimationFrame;
14
+ var cancelAnimationFrame = $window.cancelAnimationFrame || $window.webkitCancelAnimationFrame || $window.mozCancelAnimationFrame || $window.webkitCancelRequestAnimationFrame;
15
+ var rafSupported = !!requestAnimationFrame;
16
+ var raf = rafSupported ? function (fn) {
17
+ var id = requestAnimationFrame(fn);
18
+ return function () {
19
+ cancelAnimationFrame(id);
20
+ };
21
+ } : function (fn) {
22
+ var timer = $timeout(fn, 16.66, false);
23
+ // 1000 / 60 = 16.666
24
+ return function () {
25
+ $timeout.cancel(timer);
26
+ };
27
+ };
28
+ raf.supported = rafSupported;
29
+ return raf;
30
+ }
31
+ ]); // .factory('$$animateReflow', function($$rAF, $document) {
32
+ // var bodyEl = $document[0].body;
33
+ // return function(fn) {
34
+ // //the returned function acts as the cancellation function
35
+ // return $$rAF(function() {
36
+ // //the line below will force the browser to perform a repaint
37
+ // //so that all the animated elements within the animation frame
38
+ // //will be properly updated and drawn on screen. This is
39
+ // //required to perform multi-class CSS based animations with
40
+ // //Firefox. DO NOT REMOVE THIS LINE.
41
+ // var a = bodyEl.offsetWidth + 1;
42
+ // fn();
43
+ // });
44
+ // };
45
+ // });
@@ -0,0 +1,229 @@
1
+ /**
2
+ * angular-strap
3
+ * @version v2.0.1 - 2014-04-10
4
+ * @link http://mgcrea.github.io/angular-strap
5
+ * @author Olivier Louvignes (olivier@mg-crea.com)
6
+ * @license MIT License, http://www.opensource.org/licenses/MIT
7
+ */
8
+ 'use strict';
9
+ angular.module('mgcrea.ngStrap.scrollspy', [
10
+ 'mgcrea.ngStrap.helpers.debounce',
11
+ 'mgcrea.ngStrap.helpers.dimensions'
12
+ ]).provider('$scrollspy', function () {
13
+ // Pool of registered spies
14
+ var spies = this.$$spies = {};
15
+ var defaults = this.defaults = {
16
+ debounce: 150,
17
+ throttle: 100,
18
+ offset: 100
19
+ };
20
+ this.$get = [
21
+ '$window',
22
+ '$document',
23
+ '$rootScope',
24
+ 'dimensions',
25
+ 'debounce',
26
+ 'throttle',
27
+ function ($window, $document, $rootScope, dimensions, debounce, throttle) {
28
+ var windowEl = angular.element($window);
29
+ var docEl = angular.element($document.prop('documentElement'));
30
+ var bodyEl = angular.element($window.document.body);
31
+ // Helper functions
32
+ function nodeName(element, name) {
33
+ return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();
34
+ }
35
+ function ScrollSpyFactory(config) {
36
+ // Common vars
37
+ var options = angular.extend({}, defaults, config);
38
+ if (!options.element)
39
+ options.element = bodyEl;
40
+ var isWindowSpy = nodeName(options.element, 'body');
41
+ var scrollEl = isWindowSpy ? windowEl : options.element;
42
+ var scrollId = isWindowSpy ? 'window' : options.id;
43
+ // Use existing spy
44
+ if (spies[scrollId]) {
45
+ spies[scrollId].$$count++;
46
+ return spies[scrollId];
47
+ }
48
+ var $scrollspy = {};
49
+ // Private vars
50
+ var unbindViewContentLoaded, unbindIncludeContentLoaded;
51
+ var trackedElements = $scrollspy.$trackedElements = [];
52
+ var sortedElements = [];
53
+ var activeTarget;
54
+ var debouncedCheckPosition;
55
+ var throttledCheckPosition;
56
+ var debouncedCheckOffsets;
57
+ var viewportHeight;
58
+ var scrollTop;
59
+ $scrollspy.init = function () {
60
+ // Setup internal ref counter
61
+ this.$$count = 1;
62
+ // Bind events
63
+ debouncedCheckPosition = debounce(this.checkPosition, options.debounce);
64
+ throttledCheckPosition = throttle(this.checkPosition, options.throttle);
65
+ scrollEl.on('click', this.checkPositionWithEventLoop);
66
+ windowEl.on('resize', debouncedCheckPosition);
67
+ scrollEl.on('scroll', throttledCheckPosition);
68
+ debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);
69
+ unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);
70
+ unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);
71
+ debouncedCheckOffsets();
72
+ // Register spy for reuse
73
+ if (scrollId) {
74
+ spies[scrollId] = $scrollspy;
75
+ }
76
+ };
77
+ $scrollspy.destroy = function () {
78
+ // Check internal ref counter
79
+ this.$$count--;
80
+ if (this.$$count > 0) {
81
+ return;
82
+ }
83
+ // Unbind events
84
+ scrollEl.off('click', this.checkPositionWithEventLoop);
85
+ windowEl.off('resize', debouncedCheckPosition);
86
+ scrollEl.off('scroll', debouncedCheckPosition);
87
+ unbindViewContentLoaded();
88
+ unbindIncludeContentLoaded();
89
+ if (scrollId) {
90
+ delete spies[scrollId];
91
+ }
92
+ };
93
+ $scrollspy.checkPosition = function () {
94
+ // Not ready yet
95
+ if (!sortedElements.length)
96
+ return;
97
+ // Calculate the scroll position
98
+ scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;
99
+ // Calculate the viewport height for use by the components
100
+ viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));
101
+ // Activate first element if scroll is smaller
102
+ if (scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {
103
+ return $scrollspy.$activateElement(sortedElements[0]);
104
+ }
105
+ // Activate proper element
106
+ for (var i = sortedElements.length; i--;) {
107
+ if (angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null)
108
+ continue;
109
+ if (activeTarget === sortedElements[i].target)
110
+ continue;
111
+ if (scrollTop < sortedElements[i].offsetTop)
112
+ continue;
113
+ if (sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop)
114
+ continue;
115
+ return $scrollspy.$activateElement(sortedElements[i]);
116
+ }
117
+ };
118
+ $scrollspy.checkPositionWithEventLoop = function () {
119
+ setTimeout(this.checkPosition, 1);
120
+ };
121
+ // Protected methods
122
+ $scrollspy.$activateElement = function (element) {
123
+ if (activeTarget) {
124
+ var activeElement = $scrollspy.$getTrackedElement(activeTarget);
125
+ if (activeElement) {
126
+ activeElement.source.removeClass('active');
127
+ if (nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {
128
+ activeElement.source.parent().parent().removeClass('active');
129
+ }
130
+ }
131
+ }
132
+ activeTarget = element.target;
133
+ element.source.addClass('active');
134
+ if (nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {
135
+ element.source.parent().parent().addClass('active');
136
+ }
137
+ };
138
+ $scrollspy.$getTrackedElement = function (target) {
139
+ return trackedElements.filter(function (obj) {
140
+ return obj.target === target;
141
+ })[0];
142
+ };
143
+ // Track offsets behavior
144
+ $scrollspy.checkOffsets = function () {
145
+ angular.forEach(trackedElements, function (trackedElement) {
146
+ var targetElement = document.querySelector(trackedElement.target);
147
+ trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;
148
+ if (options.offset && trackedElement.offsetTop !== null)
149
+ trackedElement.offsetTop -= options.offset * 1;
150
+ });
151
+ sortedElements = trackedElements.filter(function (el) {
152
+ return el.offsetTop !== null;
153
+ }).sort(function (a, b) {
154
+ return a.offsetTop - b.offsetTop;
155
+ });
156
+ debouncedCheckPosition();
157
+ };
158
+ $scrollspy.trackElement = function (target, source) {
159
+ trackedElements.push({
160
+ target: target,
161
+ source: source
162
+ });
163
+ };
164
+ $scrollspy.untrackElement = function (target, source) {
165
+ var toDelete;
166
+ for (var i = trackedElements.length; i--;) {
167
+ if (trackedElements[i].target === target && trackedElements[i].source === source) {
168
+ toDelete = i;
169
+ break;
170
+ }
171
+ }
172
+ trackedElements = trackedElements.splice(toDelete, 1);
173
+ };
174
+ $scrollspy.activate = function (i) {
175
+ trackedElements[i].addClass('active');
176
+ };
177
+ // Initialize plugin
178
+ $scrollspy.init();
179
+ return $scrollspy;
180
+ }
181
+ return ScrollSpyFactory;
182
+ }
183
+ ];
184
+ }).directive('bsScrollspy', [
185
+ '$rootScope',
186
+ 'debounce',
187
+ 'dimensions',
188
+ '$scrollspy',
189
+ function ($rootScope, debounce, dimensions, $scrollspy) {
190
+ return {
191
+ restrict: 'EAC',
192
+ link: function postLink(scope, element, attr) {
193
+ var options = { scope: scope };
194
+ angular.forEach([
195
+ 'offset',
196
+ 'target'
197
+ ], function (key) {
198
+ if (angular.isDefined(attr[key]))
199
+ options[key] = attr[key];
200
+ });
201
+ var scrollspy = $scrollspy(options);
202
+ scrollspy.trackElement(options.target, element);
203
+ scope.$on('$destroy', function () {
204
+ scrollspy.untrackElement(options.target, element);
205
+ scrollspy.destroy();
206
+ options = null;
207
+ scrollspy = null;
208
+ });
209
+ }
210
+ };
211
+ }
212
+ ]).directive('bsScrollspyList', [
213
+ '$rootScope',
214
+ 'debounce',
215
+ 'dimensions',
216
+ '$scrollspy',
217
+ function ($rootScope, debounce, dimensions, $scrollspy) {
218
+ return {
219
+ restrict: 'A',
220
+ compile: function postLink(element, attr) {
221
+ var children = element[0].querySelectorAll('li > a[href]');
222
+ angular.forEach(children, function (child) {
223
+ var childEl = angular.element(child);
224
+ childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));
225
+ });
226
+ }
227
+ };
228
+ }
229
+ ]);