rails-angularstrap 2.2.0
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.
- checksums.yaml +7 -0
- data/README.md +89 -0
- data/Rakefile +2 -0
- data/lib/rails/angularstrap.rb +8 -0
- data/lib/rails/angularstrap/version.rb +5 -0
- data/vendor/assets/javascripts/angular-strap/LICENSE.md +21 -0
- data/vendor/assets/javascripts/angular-strap/README.md +112 -0
- data/vendor/assets/javascripts/angular-strap/angular-strap.nuspec +23 -0
- data/vendor/assets/javascripts/angular-strap/bower.json +53 -0
- data/vendor/assets/javascripts/angular-strap/dist/angular-strap.js +5014 -0
- data/vendor/assets/javascripts/angular-strap/dist/angular-strap.min.js +11 -0
- data/vendor/assets/javascripts/angular-strap/dist/angular-strap.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/angular-strap.tpl.js +89 -0
- data/vendor/assets/javascripts/angular-strap/dist/angular-strap.tpl.min.js +8 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/affix.js +249 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/affix.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/affix.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/alert.js +120 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/alert.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/alert.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/alert.tpl.js +14 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/alert.tpl.min.js +8 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/aside.js +96 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/aside.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/aside.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/aside.tpl.js +14 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/aside.tpl.min.js +8 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/button.js +177 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/button.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/button.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/collapse.js +273 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/collapse.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/collapse.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/date-formatter.js +61 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/date-formatter.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/date-formatter.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/date-parser.js +273 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/date-parser.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/date-parser.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/datepicker.js +640 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/datepicker.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/datepicker.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/datepicker.tpl.js +14 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/datepicker.tpl.min.js +8 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/debounce.js +62 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/debounce.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/debounce.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/dimensions.js +156 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/dimensions.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/dimensions.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/dropdown.js +149 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/dropdown.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/dropdown.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/dropdown.tpl.js +14 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/dropdown.tpl.min.js +8 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/modal.js +349 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/modal.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/modal.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/modal.tpl.js +14 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/modal.tpl.min.js +8 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/navbar.js +72 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/navbar.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/navbar.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/parse-options.js +76 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/parse-options.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/parse-options.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/popover.js +112 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/popover.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/popover.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/popover.tpl.js +14 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/popover.tpl.min.js +8 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/raf.js +61 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/raf.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/raf.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/scrollspy.js +261 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/scrollspy.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/scrollspy.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/select.js +325 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/select.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/select.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/select.tpl.js +14 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/select.tpl.min.js +8 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/tab.js +186 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/tab.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/tab.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/tab.tpl.js +14 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/tab.tpl.min.js +8 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/timepicker.js +485 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/timepicker.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/timepicker.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/timepicker.tpl.js +14 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/timepicker.tpl.min.js +8 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/tooltip.js +690 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/tooltip.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/tooltip.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/tooltip.tpl.js +14 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/tooltip.tpl.min.js +8 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/typeahead.js +266 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/typeahead.min.js +9 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/typeahead.min.js.map +1 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/typeahead.tpl.js +14 -0
- data/vendor/assets/javascripts/angular-strap/dist/modules/typeahead.tpl.min.js +8 -0
- data/vendor/assets/javascripts/angular-strap/gulpfile.js +489 -0
- data/vendor/assets/javascripts/angular-strap/package.json +73 -0
- data/vendor/assets/javascripts/angular-strap/src/affix/affix.js +258 -0
- data/vendor/assets/javascripts/angular-strap/src/alert/alert.js +113 -0
- data/vendor/assets/javascripts/angular-strap/src/alert/alert.tpl.html +4 -0
- data/vendor/assets/javascripts/angular-strap/src/aside/aside.js +89 -0
- data/vendor/assets/javascripts/angular-strap/src/aside/aside.tpl.html +14 -0
- data/vendor/assets/javascripts/angular-strap/src/button/button.js +174 -0
- data/vendor/assets/javascripts/angular-strap/src/collapse/collapse.js +266 -0
- data/vendor/assets/javascripts/angular-strap/src/datepicker/datepicker.js +633 -0
- data/vendor/assets/javascripts/angular-strap/src/datepicker/datepicker.tpl.html +33 -0
- data/vendor/assets/javascripts/angular-strap/src/dropdown/dropdown.js +143 -0
- data/vendor/assets/javascripts/angular-strap/src/dropdown/dropdown.tpl.html +6 -0
- data/vendor/assets/javascripts/angular-strap/src/helpers/date-formatter.js +54 -0
- data/vendor/assets/javascripts/angular-strap/src/helpers/date-parser.js +266 -0
- data/vendor/assets/javascripts/angular-strap/src/helpers/debounce.js +55 -0
- data/vendor/assets/javascripts/angular-strap/src/helpers/dimensions.js +212 -0
- data/vendor/assets/javascripts/angular-strap/src/helpers/parse-options.js +69 -0
- data/vendor/assets/javascripts/angular-strap/src/helpers/raf.js +54 -0
- data/vendor/assets/javascripts/angular-strap/src/modal/modal.js +348 -0
- data/vendor/assets/javascripts/angular-strap/src/modal/modal.tpl.html +14 -0
- data/vendor/assets/javascripts/angular-strap/src/module.js +19 -0
- data/vendor/assets/javascripts/angular-strap/src/navbar/navbar.js +65 -0
- data/vendor/assets/javascripts/angular-strap/src/popover/popover.js +111 -0
- data/vendor/assets/javascripts/angular-strap/src/popover/popover.tpl.html +5 -0
- data/vendor/assets/javascripts/angular-strap/src/scrollspy/scrollspy.js +254 -0
- data/vendor/assets/javascripts/angular-strap/src/select/select.js +321 -0
- data/vendor/assets/javascripts/angular-strap/src/select/select.tpl.html +14 -0
- data/vendor/assets/javascripts/angular-strap/src/tab/tab.js +183 -0
- data/vendor/assets/javascripts/angular-strap/src/tab/tab.tpl.html +7 -0
- data/vendor/assets/javascripts/angular-strap/src/timepicker/timepicker.js +493 -0
- data/vendor/assets/javascripts/angular-strap/src/timepicker/timepicker.tpl.html +62 -0
- data/vendor/assets/javascripts/angular-strap/src/tooltip/tooltip.js +806 -0
- data/vendor/assets/javascripts/angular-strap/src/tooltip/tooltip.tpl.html +4 -0
- data/vendor/assets/javascripts/angular-strap/src/typeahead/typeahead.js +262 -0
- data/vendor/assets/javascripts/angular-strap/src/typeahead/typeahead.tpl.html +5 -0
- data/vendor/assets/javascripts/angular/README.md +64 -0
- data/vendor/assets/javascripts/angular/angular-csp.css +13 -0
- data/vendor/assets/javascripts/angular/angular.js +26181 -0
- data/vendor/assets/javascripts/angular/angular.min.js +250 -0
- data/vendor/assets/javascripts/angular/angular.min.js.gzip +0 -0
- data/vendor/assets/javascripts/angular/angular.min.js.map +8 -0
- data/vendor/assets/javascripts/angular/bower.json +8 -0
- data/vendor/assets/javascripts/angular/index.js +2 -0
- data/vendor/assets/javascripts/angular/package.json +25 -0
- metadata +237 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<div class="modal" tabindex="-1" role="dialog">
|
|
2
|
+
<div class="modal-dialog">
|
|
3
|
+
<div class="modal-content">
|
|
4
|
+
<div class="modal-header" ng-show="title">
|
|
5
|
+
<button type="button" class="close" ng-click="$hide()">×</button>
|
|
6
|
+
<h4 class="modal-title" ng-bind="title"></h4>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="modal-body" ng-bind="content"></div>
|
|
9
|
+
<div class="modal-footer">
|
|
10
|
+
<button type="button" class="btn btn-default" ng-click="$hide()">Close</button>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
angular.module('mgcrea.ngStrap', [
|
|
3
|
+
'mgcrea.ngStrap.modal',
|
|
4
|
+
'mgcrea.ngStrap.aside',
|
|
5
|
+
'mgcrea.ngStrap.alert',
|
|
6
|
+
'mgcrea.ngStrap.button',
|
|
7
|
+
'mgcrea.ngStrap.select',
|
|
8
|
+
'mgcrea.ngStrap.datepicker',
|
|
9
|
+
'mgcrea.ngStrap.timepicker',
|
|
10
|
+
'mgcrea.ngStrap.navbar',
|
|
11
|
+
'mgcrea.ngStrap.tooltip',
|
|
12
|
+
'mgcrea.ngStrap.popover',
|
|
13
|
+
'mgcrea.ngStrap.dropdown',
|
|
14
|
+
'mgcrea.ngStrap.typeahead',
|
|
15
|
+
'mgcrea.ngStrap.scrollspy',
|
|
16
|
+
'mgcrea.ngStrap.affix',
|
|
17
|
+
'mgcrea.ngStrap.tab',
|
|
18
|
+
'mgcrea.ngStrap.collapse'
|
|
19
|
+
]);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
angular.module('mgcrea.ngStrap.navbar', [])
|
|
4
|
+
|
|
5
|
+
.provider('$navbar', function() {
|
|
6
|
+
|
|
7
|
+
var defaults = this.defaults = {
|
|
8
|
+
activeClass: 'active',
|
|
9
|
+
routeAttr: 'data-match-route',
|
|
10
|
+
strict: false
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
this.$get = function() {
|
|
14
|
+
return {defaults: defaults};
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
.directive('bsNavbar', function($window, $location, $navbar) {
|
|
20
|
+
|
|
21
|
+
var defaults = $navbar.defaults;
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
restrict: 'A',
|
|
25
|
+
link: function postLink(scope, element, attr, controller) {
|
|
26
|
+
|
|
27
|
+
// Directive options
|
|
28
|
+
var options = angular.copy(defaults);
|
|
29
|
+
angular.forEach(Object.keys(defaults), function(key) {
|
|
30
|
+
if(angular.isDefined(attr[key])) options[key] = attr[key];
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Watch for the $location
|
|
34
|
+
scope.$watch(function() {
|
|
35
|
+
|
|
36
|
+
return $location.path();
|
|
37
|
+
|
|
38
|
+
}, function(newValue, oldValue) {
|
|
39
|
+
|
|
40
|
+
var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');
|
|
41
|
+
|
|
42
|
+
angular.forEach(liElements, function(li) {
|
|
43
|
+
|
|
44
|
+
var liElement = angular.element(li);
|
|
45
|
+
var pattern = liElement.attr(options.routeAttr).replace('/', '\\/');
|
|
46
|
+
if(options.strict) {
|
|
47
|
+
pattern = '^' + pattern + '$';
|
|
48
|
+
}
|
|
49
|
+
var regexp = new RegExp(pattern, ['i']);
|
|
50
|
+
|
|
51
|
+
if(regexp.test(newValue)) {
|
|
52
|
+
liElement.addClass(options.activeClass);
|
|
53
|
+
} else {
|
|
54
|
+
liElement.removeClass(options.activeClass);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
angular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])
|
|
4
|
+
|
|
5
|
+
.provider('$popover', function() {
|
|
6
|
+
|
|
7
|
+
var defaults = this.defaults = {
|
|
8
|
+
animation: 'am-fade',
|
|
9
|
+
customClass: '',
|
|
10
|
+
container: false,
|
|
11
|
+
target: false,
|
|
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
|
+
autoClose: false
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
this.$get = function($tooltip) {
|
|
25
|
+
|
|
26
|
+
function PopoverFactory(element, config) {
|
|
27
|
+
|
|
28
|
+
// Common vars
|
|
29
|
+
var options = angular.extend({}, defaults, config);
|
|
30
|
+
|
|
31
|
+
var $popover = $tooltip(element, options);
|
|
32
|
+
|
|
33
|
+
// Support scope as string options [/*title, */content]
|
|
34
|
+
if(options.content) {
|
|
35
|
+
$popover.$scope.content = options.content;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return $popover;
|
|
39
|
+
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return PopoverFactory;
|
|
43
|
+
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
.directive('bsPopover', function($window, $sce, $popover) {
|
|
49
|
+
|
|
50
|
+
var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
restrict: 'EAC',
|
|
54
|
+
scope: true,
|
|
55
|
+
link: function postLink(scope, element, attr) {
|
|
56
|
+
|
|
57
|
+
// Directive options
|
|
58
|
+
var options = {scope: scope};
|
|
59
|
+
angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'customClass', 'autoClose', 'id'], function(key) {
|
|
60
|
+
if(angular.isDefined(attr[key])) options[key] = attr[key];
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Support scope as data-attrs
|
|
64
|
+
angular.forEach(['title', 'content'], function(key) {
|
|
65
|
+
attr[key] && attr.$observe(key, function(newValue, oldValue) {
|
|
66
|
+
scope[key] = $sce.trustAsHtml(newValue);
|
|
67
|
+
angular.isDefined(oldValue) && requestAnimationFrame(function() {
|
|
68
|
+
popover && popover.$applyPlacement();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Support scope as an object
|
|
74
|
+
attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {
|
|
75
|
+
if(angular.isObject(newValue)) {
|
|
76
|
+
angular.extend(scope, newValue);
|
|
77
|
+
} else {
|
|
78
|
+
scope.content = newValue;
|
|
79
|
+
}
|
|
80
|
+
angular.isDefined(oldValue) && requestAnimationFrame(function() {
|
|
81
|
+
popover && popover.$applyPlacement();
|
|
82
|
+
});
|
|
83
|
+
}, true);
|
|
84
|
+
|
|
85
|
+
// Visibility binding support
|
|
86
|
+
attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {
|
|
87
|
+
if(!popover || !angular.isDefined(newValue)) return;
|
|
88
|
+
if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);
|
|
89
|
+
newValue === true ? popover.show() : popover.hide();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Viewport support
|
|
93
|
+
attr.viewport && scope.$watch(attr.viewport, function (newValue) {
|
|
94
|
+
if(!popover || !angular.isDefined(newValue)) return;
|
|
95
|
+
popover.setViewport(newValue);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Initialize popover
|
|
99
|
+
var popover = $popover(element, options);
|
|
100
|
+
|
|
101
|
+
// Garbage collection
|
|
102
|
+
scope.$on('$destroy', function() {
|
|
103
|
+
if (popover) popover.destroy();
|
|
104
|
+
options = null;
|
|
105
|
+
popover = null;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
});
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
angular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', 'mgcrea.ngStrap.helpers.dimensions'])
|
|
4
|
+
|
|
5
|
+
.provider('$scrollspy', function() {
|
|
6
|
+
|
|
7
|
+
// Pool of registered spies
|
|
8
|
+
var spies = this.$$spies = {};
|
|
9
|
+
|
|
10
|
+
var defaults = this.defaults = {
|
|
11
|
+
debounce: 150,
|
|
12
|
+
throttle: 100,
|
|
13
|
+
offset: 100
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
this.$get = function($window, $document, $rootScope, dimensions, debounce, throttle) {
|
|
17
|
+
|
|
18
|
+
var windowEl = angular.element($window);
|
|
19
|
+
var docEl = angular.element($document.prop('documentElement'));
|
|
20
|
+
var bodyEl = angular.element($window.document.body);
|
|
21
|
+
|
|
22
|
+
// Helper functions
|
|
23
|
+
|
|
24
|
+
function nodeName(element, name) {
|
|
25
|
+
return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function ScrollSpyFactory(config) {
|
|
29
|
+
|
|
30
|
+
// Common vars
|
|
31
|
+
var options = angular.extend({}, defaults, config);
|
|
32
|
+
if(!options.element) options.element = bodyEl;
|
|
33
|
+
var isWindowSpy = nodeName(options.element, 'body');
|
|
34
|
+
var scrollEl = isWindowSpy ? windowEl : options.element;
|
|
35
|
+
var scrollId = isWindowSpy ? 'window' : options.id;
|
|
36
|
+
|
|
37
|
+
// Use existing spy
|
|
38
|
+
if(spies[scrollId]) {
|
|
39
|
+
spies[scrollId].$$count++;
|
|
40
|
+
return spies[scrollId];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
var $scrollspy = {};
|
|
44
|
+
|
|
45
|
+
// Private vars
|
|
46
|
+
var unbindViewContentLoaded, unbindIncludeContentLoaded;
|
|
47
|
+
var trackedElements = $scrollspy.$trackedElements = [];
|
|
48
|
+
var sortedElements = [];
|
|
49
|
+
var activeTarget;
|
|
50
|
+
var debouncedCheckPosition;
|
|
51
|
+
var throttledCheckPosition;
|
|
52
|
+
var debouncedCheckOffsets;
|
|
53
|
+
var viewportHeight;
|
|
54
|
+
var scrollTop;
|
|
55
|
+
|
|
56
|
+
$scrollspy.init = function() {
|
|
57
|
+
|
|
58
|
+
// Setup internal ref counter
|
|
59
|
+
this.$$count = 1;
|
|
60
|
+
|
|
61
|
+
// Bind events
|
|
62
|
+
debouncedCheckPosition = debounce(this.checkPosition, options.debounce);
|
|
63
|
+
throttledCheckPosition = throttle(this.checkPosition, options.throttle);
|
|
64
|
+
scrollEl.on('click', this.checkPositionWithEventLoop);
|
|
65
|
+
windowEl.on('resize', debouncedCheckPosition);
|
|
66
|
+
scrollEl.on('scroll', throttledCheckPosition);
|
|
67
|
+
|
|
68
|
+
debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);
|
|
69
|
+
unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);
|
|
70
|
+
unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);
|
|
71
|
+
debouncedCheckOffsets();
|
|
72
|
+
|
|
73
|
+
// Register spy for reuse
|
|
74
|
+
if(scrollId) {
|
|
75
|
+
spies[scrollId] = $scrollspy;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
$scrollspy.destroy = function() {
|
|
81
|
+
|
|
82
|
+
// Check internal ref counter
|
|
83
|
+
this.$$count--;
|
|
84
|
+
if(this.$$count > 0) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Unbind events
|
|
89
|
+
scrollEl.off('click', this.checkPositionWithEventLoop);
|
|
90
|
+
windowEl.off('resize', debouncedCheckPosition);
|
|
91
|
+
scrollEl.off('scroll', throttledCheckPosition);
|
|
92
|
+
unbindViewContentLoaded();
|
|
93
|
+
unbindIncludeContentLoaded();
|
|
94
|
+
if (scrollId) {
|
|
95
|
+
delete spies[scrollId];
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
$scrollspy.checkPosition = function() {
|
|
100
|
+
|
|
101
|
+
// Not ready yet
|
|
102
|
+
if(!sortedElements.length) return;
|
|
103
|
+
|
|
104
|
+
// Calculate the scroll position
|
|
105
|
+
scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;
|
|
106
|
+
|
|
107
|
+
// Calculate the viewport height for use by the components
|
|
108
|
+
viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));
|
|
109
|
+
|
|
110
|
+
// Activate first element if scroll is smaller
|
|
111
|
+
if(scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {
|
|
112
|
+
return $scrollspy.$activateElement(sortedElements[0]);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Activate proper element
|
|
116
|
+
for (var i = sortedElements.length; i--;) {
|
|
117
|
+
if(angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) continue;
|
|
118
|
+
if(activeTarget === sortedElements[i].target) continue;
|
|
119
|
+
if(scrollTop < sortedElements[i].offsetTop) continue;
|
|
120
|
+
if(sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) continue;
|
|
121
|
+
return $scrollspy.$activateElement(sortedElements[i]);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
$scrollspy.checkPositionWithEventLoop = function() {
|
|
127
|
+
// IE 9 throws an error if we use 'this' instead of '$scrollspy'
|
|
128
|
+
// in this setTimeout call
|
|
129
|
+
setTimeout($scrollspy.checkPosition, 1);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// Protected methods
|
|
133
|
+
|
|
134
|
+
$scrollspy.$activateElement = function(element) {
|
|
135
|
+
if(activeTarget) {
|
|
136
|
+
var activeElement = $scrollspy.$getTrackedElement(activeTarget);
|
|
137
|
+
if(activeElement) {
|
|
138
|
+
activeElement.source.removeClass('active');
|
|
139
|
+
if(nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {
|
|
140
|
+
activeElement.source.parent().parent().removeClass('active');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
activeTarget = element.target;
|
|
145
|
+
element.source.addClass('active');
|
|
146
|
+
if(nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {
|
|
147
|
+
element.source.parent().parent().addClass('active');
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
$scrollspy.$getTrackedElement = function(target) {
|
|
152
|
+
return trackedElements.filter(function(obj) {
|
|
153
|
+
return obj.target === target;
|
|
154
|
+
})[0];
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
// Track offsets behavior
|
|
158
|
+
|
|
159
|
+
$scrollspy.checkOffsets = function() {
|
|
160
|
+
|
|
161
|
+
angular.forEach(trackedElements, function(trackedElement) {
|
|
162
|
+
var targetElement = document.querySelector(trackedElement.target);
|
|
163
|
+
trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;
|
|
164
|
+
if(options.offset && trackedElement.offsetTop !== null) trackedElement.offsetTop -= options.offset * 1;
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
sortedElements = trackedElements
|
|
168
|
+
.filter(function(el) {
|
|
169
|
+
return el.offsetTop !== null;
|
|
170
|
+
})
|
|
171
|
+
.sort(function(a, b) {
|
|
172
|
+
return a.offsetTop - b.offsetTop;
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
debouncedCheckPosition();
|
|
176
|
+
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
$scrollspy.trackElement = function(target, source) {
|
|
180
|
+
trackedElements.push({target: target, source: source});
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
$scrollspy.untrackElement = function(target, source) {
|
|
184
|
+
var toDelete;
|
|
185
|
+
for (var i = trackedElements.length; i--;) {
|
|
186
|
+
if(trackedElements[i].target === target && trackedElements[i].source === source) {
|
|
187
|
+
toDelete = i;
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
trackedElements = trackedElements.splice(toDelete, 1);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
$scrollspy.activate = function(i) {
|
|
195
|
+
trackedElements[i].addClass('active');
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// Initialize plugin
|
|
199
|
+
|
|
200
|
+
$scrollspy.init();
|
|
201
|
+
return $scrollspy;
|
|
202
|
+
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return ScrollSpyFactory;
|
|
206
|
+
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
.directive('bsScrollspy', function($rootScope, debounce, dimensions, $scrollspy) {
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
restrict: 'EAC',
|
|
215
|
+
link: function postLink(scope, element, attr) {
|
|
216
|
+
|
|
217
|
+
var options = {scope: scope};
|
|
218
|
+
angular.forEach(['offset', 'target'], function(key) {
|
|
219
|
+
if(angular.isDefined(attr[key])) options[key] = attr[key];
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
var scrollspy = $scrollspy(options);
|
|
223
|
+
scrollspy.trackElement(options.target, element);
|
|
224
|
+
|
|
225
|
+
scope.$on('$destroy', function() {
|
|
226
|
+
if (scrollspy) {
|
|
227
|
+
scrollspy.untrackElement(options.target, element);
|
|
228
|
+
scrollspy.destroy();
|
|
229
|
+
}
|
|
230
|
+
options = null;
|
|
231
|
+
scrollspy = null;
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
.directive('bsScrollspyList', function($rootScope, debounce, dimensions, $scrollspy) {
|
|
241
|
+
|
|
242
|
+
return {
|
|
243
|
+
restrict: 'A',
|
|
244
|
+
compile: function postLink(element, attr) {
|
|
245
|
+
var children = element[0].querySelectorAll('li > a[href]');
|
|
246
|
+
angular.forEach(children, function(child) {
|
|
247
|
+
var childEl = angular.element(child);
|
|
248
|
+
childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
});
|