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.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +45 -0
- data/Rakefile +1 -0
- data/angular-strap-rails.gemspec +15 -0
- data/lib/angular-strap-rails.rb +8 -0
- data/lib/angular-strap-rails/version.rb +5 -0
- data/vendor/.DS_Store +0 -0
- data/vendor/assets/.DS_Store +0 -0
- data/vendor/assets/javascripts/.DS_Store +0 -0
- data/vendor/assets/javascripts/angular-strap.coffee +0 -0
- data/vendor/assets/javascripts/angular-strap/.DS_Store +0 -0
- data/vendor/assets/javascripts/angular-strap/datepicker.coffee +11 -0
- data/vendor/assets/javascripts/angular-strap/modal.coffee +9 -0
- data/vendor/assets/javascripts/dist/angular-strap.js +3682 -0
- data/vendor/assets/javascripts/dist/angular-strap.tpl.js +100 -0
- data/vendor/assets/javascripts/dist/modules/affix.js +191 -0
- data/vendor/assets/javascripts/dist/modules/alert.js +114 -0
- data/vendor/assets/javascripts/dist/modules/alert.tpl.js +14 -0
- data/vendor/assets/javascripts/dist/modules/aside.js +96 -0
- data/vendor/assets/javascripts/dist/modules/aside.tpl.js +14 -0
- data/vendor/assets/javascripts/dist/modules/button.js +141 -0
- data/vendor/assets/javascripts/dist/modules/date-parser.js +150 -0
- data/vendor/assets/javascripts/dist/modules/datepicker.js +583 -0
- data/vendor/assets/javascripts/dist/modules/datepicker.tpl.js +14 -0
- data/vendor/assets/javascripts/dist/modules/debounce.js +60 -0
- data/vendor/assets/javascripts/dist/modules/dimensions.js +142 -0
- data/vendor/assets/javascripts/dist/modules/dropdown.js +124 -0
- data/vendor/assets/javascripts/dist/modules/dropdown.tpl.js +14 -0
- data/vendor/assets/javascripts/dist/modules/modal.js +282 -0
- data/vendor/assets/javascripts/dist/modules/modal.tpl.js +14 -0
- data/vendor/assets/javascripts/dist/modules/navbar.js +55 -0
- data/vendor/assets/javascripts/dist/modules/parse-options.js +51 -0
- data/vendor/assets/javascripts/dist/modules/popover.js +100 -0
- data/vendor/assets/javascripts/dist/modules/popover.tpl.js +14 -0
- data/vendor/assets/javascripts/dist/modules/raf.js +45 -0
- data/vendor/assets/javascripts/dist/modules/scrollspy.js +229 -0
- data/vendor/assets/javascripts/dist/modules/select.js +281 -0
- data/vendor/assets/javascripts/dist/modules/select.tpl.js +14 -0
- data/vendor/assets/javascripts/dist/modules/tab.js +69 -0
- data/vendor/assets/javascripts/dist/modules/tab.tpl.js +14 -0
- data/vendor/assets/javascripts/dist/modules/timepicker.js +430 -0
- data/vendor/assets/javascripts/dist/modules/timepicker.tpl.js +14 -0
- data/vendor/assets/javascripts/dist/modules/tooltip.js +405 -0
- data/vendor/assets/javascripts/dist/modules/tooltip.tpl.js +14 -0
- data/vendor/assets/javascripts/dist/modules/typeahead.js +225 -0
- data/vendor/assets/javascripts/dist/modules/typeahead.tpl.js +14 -0
- data/vendor/assets/stylesheets/angular-strap.css +564 -0
- 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.datepicker').run([
|
|
10
|
+
'$templateCache',
|
|
11
|
+
function ($templateCache) {
|
|
12
|
+
$templateCache.put('datepicker/datepicker.tpl.html', '<div class="dropdown-menu datepicker" ng-class="\'datepicker-mode-\' + $mode" style="max-width: 320px"><table style="table-layout: fixed; height: 100%; width: 100%"><thead><tr class="text-center"><th><button tabindex="-1" type="button" class="btn btn-default pull-left" ng-click="$selectPane(-1)"><i class="glyphicon glyphicon-chevron-left"></i></button></th><th colspan="{{ rows[0].length - 2 }}"><button tabindex="-1" type="button" class="btn btn-default btn-block text-strong" ng-click="$toggleMode()"><strong style="text-transform: capitalize" ng-bind="title"></strong></button></th><th><button tabindex="-1" type="button" class="btn btn-default pull-right" ng-click="$selectPane(+1)"><i class="glyphicon glyphicon-chevron-right"></i></button></th></tr><tr ng-show="labels" ng-bind-html="labels"></tr></thead><tbody><tr ng-repeat="(i, row) in rows" height="{{ 100 / rows.length }}%"><td class="text-center" ng-repeat="(j, el) in row"><button tabindex="-1" type="button" class="btn btn-default" style="width: 100%" ng-class="{\'btn-primary\': el.selected}" ng-click="$select(el.date)" ng-disabled="el.disabled"><span ng-class="{\'text-muted\': el.muted}" ng-bind="el.label"></span></button></td></tr></tbody></table></div>');
|
|
13
|
+
}
|
|
14
|
+
]);
|
|
@@ -0,0 +1,60 @@
|
|
|
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.debounce', []).constant('debounce', function (func, wait, immediate) {
|
|
10
|
+
var timeout, args, context, timestamp, result;
|
|
11
|
+
return function () {
|
|
12
|
+
context = this;
|
|
13
|
+
args = arguments;
|
|
14
|
+
timestamp = new Date();
|
|
15
|
+
var later = function () {
|
|
16
|
+
var last = new Date() - timestamp;
|
|
17
|
+
if (last < wait) {
|
|
18
|
+
timeout = setTimeout(later, wait - last);
|
|
19
|
+
} else {
|
|
20
|
+
timeout = null;
|
|
21
|
+
if (!immediate)
|
|
22
|
+
result = func.apply(context, args);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
var callNow = immediate && !timeout;
|
|
26
|
+
if (!timeout) {
|
|
27
|
+
timeout = setTimeout(later, wait);
|
|
28
|
+
}
|
|
29
|
+
if (callNow)
|
|
30
|
+
result = func.apply(context, args);
|
|
31
|
+
return result;
|
|
32
|
+
};
|
|
33
|
+
}).constant('throttle', function (func, wait, options) {
|
|
34
|
+
var context, args, result;
|
|
35
|
+
var timeout = null;
|
|
36
|
+
var previous = 0;
|
|
37
|
+
options || (options = {});
|
|
38
|
+
var later = function () {
|
|
39
|
+
previous = options.leading === false ? 0 : new Date();
|
|
40
|
+
timeout = null;
|
|
41
|
+
result = func.apply(context, args);
|
|
42
|
+
};
|
|
43
|
+
return function () {
|
|
44
|
+
var now = new Date();
|
|
45
|
+
if (!previous && options.leading === false)
|
|
46
|
+
previous = now;
|
|
47
|
+
var remaining = wait - (now - previous);
|
|
48
|
+
context = this;
|
|
49
|
+
args = arguments;
|
|
50
|
+
if (remaining <= 0) {
|
|
51
|
+
clearTimeout(timeout);
|
|
52
|
+
timeout = null;
|
|
53
|
+
previous = now;
|
|
54
|
+
result = func.apply(context, args);
|
|
55
|
+
} else if (!timeout && options.trailing !== false) {
|
|
56
|
+
timeout = setTimeout(later, remaining);
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
};
|
|
60
|
+
});
|
|
@@ -0,0 +1,142 @@
|
|
|
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.dimensions', []).factory('dimensions', [
|
|
10
|
+
'$document',
|
|
11
|
+
'$window',
|
|
12
|
+
function ($document, $window) {
|
|
13
|
+
var jqLite = angular.element;
|
|
14
|
+
var fn = {};
|
|
15
|
+
/**
|
|
16
|
+
* Test the element nodeName
|
|
17
|
+
* @param element
|
|
18
|
+
* @param name
|
|
19
|
+
*/
|
|
20
|
+
var nodeName = fn.nodeName = function (element, name) {
|
|
21
|
+
return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Returns the element computed style
|
|
25
|
+
* @param element
|
|
26
|
+
* @param prop
|
|
27
|
+
* @param extra
|
|
28
|
+
*/
|
|
29
|
+
fn.css = function (element, prop, extra) {
|
|
30
|
+
var value;
|
|
31
|
+
if (element.currentStyle) {
|
|
32
|
+
//IE
|
|
33
|
+
value = element.currentStyle[prop];
|
|
34
|
+
} else if (window.getComputedStyle) {
|
|
35
|
+
value = window.getComputedStyle(element)[prop];
|
|
36
|
+
} else {
|
|
37
|
+
value = element.style[prop];
|
|
38
|
+
}
|
|
39
|
+
return extra === true ? parseFloat(value) || 0 : value;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Provides read-only equivalent of jQuery's offset function:
|
|
43
|
+
* @required-by bootstrap-tooltip, bootstrap-affix
|
|
44
|
+
* @url http://api.jquery.com/offset/
|
|
45
|
+
* @param element
|
|
46
|
+
*/
|
|
47
|
+
fn.offset = function (element) {
|
|
48
|
+
var boxRect = element.getBoundingClientRect();
|
|
49
|
+
var docElement = element.ownerDocument;
|
|
50
|
+
return {
|
|
51
|
+
width: element.offsetWidth,
|
|
52
|
+
height: element.offsetHeight,
|
|
53
|
+
top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),
|
|
54
|
+
left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Provides read-only equivalent of jQuery's position function
|
|
59
|
+
* @required-by bootstrap-tooltip, bootstrap-affix
|
|
60
|
+
* @url http://api.jquery.com/offset/
|
|
61
|
+
* @param element
|
|
62
|
+
*/
|
|
63
|
+
fn.position = function (element) {
|
|
64
|
+
var offsetParentRect = {
|
|
65
|
+
top: 0,
|
|
66
|
+
left: 0
|
|
67
|
+
}, offsetParentElement, offset;
|
|
68
|
+
// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
|
|
69
|
+
if (fn.css(element, 'position') === 'fixed') {
|
|
70
|
+
// We assume that getBoundingClientRect is available when computed position is fixed
|
|
71
|
+
offset = element.getBoundingClientRect();
|
|
72
|
+
} else {
|
|
73
|
+
// Get *real* offsetParentElement
|
|
74
|
+
offsetParentElement = offsetParent(element);
|
|
75
|
+
offset = fn.offset(element);
|
|
76
|
+
// Get correct offsets
|
|
77
|
+
offset = fn.offset(element);
|
|
78
|
+
if (!nodeName(offsetParentElement, 'html')) {
|
|
79
|
+
offsetParentRect = fn.offset(offsetParentElement);
|
|
80
|
+
}
|
|
81
|
+
// Add offsetParent borders
|
|
82
|
+
offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);
|
|
83
|
+
offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);
|
|
84
|
+
}
|
|
85
|
+
// Subtract parent offsets and element margins
|
|
86
|
+
return {
|
|
87
|
+
width: element.offsetWidth,
|
|
88
|
+
height: element.offsetHeight,
|
|
89
|
+
top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),
|
|
90
|
+
left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Returns the closest, non-statically positioned offsetParent of a given element
|
|
95
|
+
* @required-by fn.position
|
|
96
|
+
* @param element
|
|
97
|
+
*/
|
|
98
|
+
var offsetParent = function offsetParentElement(element) {
|
|
99
|
+
var docElement = element.ownerDocument;
|
|
100
|
+
var offsetParent = element.offsetParent || docElement;
|
|
101
|
+
if (nodeName(offsetParent, '#document'))
|
|
102
|
+
return docElement.documentElement;
|
|
103
|
+
while (offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {
|
|
104
|
+
offsetParent = offsetParent.offsetParent;
|
|
105
|
+
}
|
|
106
|
+
return offsetParent || docElement.documentElement;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Provides equivalent of jQuery's height function
|
|
110
|
+
* @required-by bootstrap-affix
|
|
111
|
+
* @url http://api.jquery.com/height/
|
|
112
|
+
* @param element
|
|
113
|
+
* @param outer
|
|
114
|
+
*/
|
|
115
|
+
fn.height = function (element, outer) {
|
|
116
|
+
var value = element.offsetHeight;
|
|
117
|
+
if (outer) {
|
|
118
|
+
value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);
|
|
119
|
+
} else {
|
|
120
|
+
value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);
|
|
121
|
+
}
|
|
122
|
+
return value;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Provides equivalent of jQuery's height function
|
|
126
|
+
* @required-by bootstrap-affix
|
|
127
|
+
* @url http://api.jquery.com/width/
|
|
128
|
+
* @param element
|
|
129
|
+
* @param outer
|
|
130
|
+
*/
|
|
131
|
+
fn.width = function (element, outer) {
|
|
132
|
+
var value = element.offsetWidth;
|
|
133
|
+
if (outer) {
|
|
134
|
+
value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);
|
|
135
|
+
} else {
|
|
136
|
+
value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);
|
|
137
|
+
}
|
|
138
|
+
return value;
|
|
139
|
+
};
|
|
140
|
+
return fn;
|
|
141
|
+
}
|
|
142
|
+
]);
|
|
@@ -0,0 +1,124 @@
|
|
|
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.dropdown', ['mgcrea.ngStrap.tooltip']).provider('$dropdown', function () {
|
|
10
|
+
var defaults = this.defaults = {
|
|
11
|
+
animation: 'am-fade',
|
|
12
|
+
prefixClass: 'dropdown',
|
|
13
|
+
placement: 'bottom-left',
|
|
14
|
+
template: 'dropdown/dropdown.tpl.html',
|
|
15
|
+
trigger: 'click',
|
|
16
|
+
container: false,
|
|
17
|
+
keyboard: true,
|
|
18
|
+
html: false,
|
|
19
|
+
delay: 0
|
|
20
|
+
};
|
|
21
|
+
this.$get = [
|
|
22
|
+
'$window',
|
|
23
|
+
'$rootScope',
|
|
24
|
+
'$tooltip',
|
|
25
|
+
function ($window, $rootScope, $tooltip) {
|
|
26
|
+
var bodyEl = angular.element($window.document.body);
|
|
27
|
+
var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;
|
|
28
|
+
function DropdownFactory(element, config) {
|
|
29
|
+
var $dropdown = {};
|
|
30
|
+
// Common vars
|
|
31
|
+
var options = angular.extend({}, defaults, config);
|
|
32
|
+
var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();
|
|
33
|
+
$dropdown = $tooltip(element, options);
|
|
34
|
+
// Protected methods
|
|
35
|
+
$dropdown.$onKeyDown = function (evt) {
|
|
36
|
+
if (!/(38|40)/.test(evt.keyCode))
|
|
37
|
+
return;
|
|
38
|
+
evt.preventDefault();
|
|
39
|
+
evt.stopPropagation();
|
|
40
|
+
// Retrieve focused index
|
|
41
|
+
var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));
|
|
42
|
+
if (!items.length)
|
|
43
|
+
return;
|
|
44
|
+
var index;
|
|
45
|
+
angular.forEach(items, function (el, i) {
|
|
46
|
+
if (matchesSelector && matchesSelector.call(el, ':focus'))
|
|
47
|
+
index = i;
|
|
48
|
+
});
|
|
49
|
+
// Navigate with keyboard
|
|
50
|
+
if (evt.keyCode === 38 && index > 0)
|
|
51
|
+
index--;
|
|
52
|
+
else if (evt.keyCode === 40 && index < items.length - 1)
|
|
53
|
+
index++;
|
|
54
|
+
else if (angular.isUndefined(index))
|
|
55
|
+
index = 0;
|
|
56
|
+
items.eq(index)[0].focus();
|
|
57
|
+
};
|
|
58
|
+
// Overrides
|
|
59
|
+
var show = $dropdown.show;
|
|
60
|
+
$dropdown.show = function () {
|
|
61
|
+
show();
|
|
62
|
+
setTimeout(function () {
|
|
63
|
+
options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);
|
|
64
|
+
bodyEl.on('click', onBodyClick);
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
var hide = $dropdown.hide;
|
|
68
|
+
$dropdown.hide = function () {
|
|
69
|
+
options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);
|
|
70
|
+
bodyEl.off('click', onBodyClick);
|
|
71
|
+
hide();
|
|
72
|
+
};
|
|
73
|
+
// Private functions
|
|
74
|
+
function onBodyClick(evt) {
|
|
75
|
+
if (evt.target === element[0])
|
|
76
|
+
return;
|
|
77
|
+
return evt.target !== element[0] && $dropdown.hide();
|
|
78
|
+
}
|
|
79
|
+
return $dropdown;
|
|
80
|
+
}
|
|
81
|
+
return DropdownFactory;
|
|
82
|
+
}
|
|
83
|
+
];
|
|
84
|
+
}).directive('bsDropdown', [
|
|
85
|
+
'$window',
|
|
86
|
+
'$location',
|
|
87
|
+
'$sce',
|
|
88
|
+
'$dropdown',
|
|
89
|
+
function ($window, $location, $sce, $dropdown) {
|
|
90
|
+
return {
|
|
91
|
+
restrict: 'EAC',
|
|
92
|
+
scope: true,
|
|
93
|
+
link: function postLink(scope, element, attr, transclusion) {
|
|
94
|
+
// Directive options
|
|
95
|
+
var options = { scope: scope };
|
|
96
|
+
angular.forEach([
|
|
97
|
+
'placement',
|
|
98
|
+
'container',
|
|
99
|
+
'delay',
|
|
100
|
+
'trigger',
|
|
101
|
+
'keyboard',
|
|
102
|
+
'html',
|
|
103
|
+
'animation',
|
|
104
|
+
'template'
|
|
105
|
+
], function (key) {
|
|
106
|
+
if (angular.isDefined(attr[key]))
|
|
107
|
+
options[key] = attr[key];
|
|
108
|
+
});
|
|
109
|
+
// Support scope as an object
|
|
110
|
+
attr.bsDropdown && scope.$watch(attr.bsDropdown, function (newValue, oldValue) {
|
|
111
|
+
scope.content = newValue;
|
|
112
|
+
}, true);
|
|
113
|
+
// Initialize dropdown
|
|
114
|
+
var dropdown = $dropdown(element, options);
|
|
115
|
+
// Garbage collection
|
|
116
|
+
scope.$on('$destroy', function () {
|
|
117
|
+
dropdown.destroy();
|
|
118
|
+
options = null;
|
|
119
|
+
dropdown = null;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
]);
|
|
@@ -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.dropdown').run([
|
|
10
|
+
'$templateCache',
|
|
11
|
+
function ($templateCache) {
|
|
12
|
+
$templateCache.put('dropdown/dropdown.tpl.html', '<ul tabindex="-1" class="dropdown-menu" role="menu"><li role="presentation" ng-class="{divider: item.divider}" ng-repeat="item in content"><a role="menuitem" tabindex="-1" ng-href="{{item.href}}" ng-if="!item.divider && item.href" ng-bind="item.text"></a> <a role="menuitem" tabindex="-1" href="javascript:void(0)" ng-if="!item.divider && item.click" ng-click="$eval(item.click);$hide()" ng-bind="item.text"></a></li></ul>');
|
|
13
|
+
}
|
|
14
|
+
]);
|
|
@@ -0,0 +1,282 @@
|
|
|
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', ['mgcrea.ngStrap.helpers.dimensions']).provider('$modal', function () {
|
|
10
|
+
var defaults = this.defaults = {
|
|
11
|
+
animation: 'am-fade',
|
|
12
|
+
backdropAnimation: 'am-fade',
|
|
13
|
+
prefixClass: 'modal',
|
|
14
|
+
prefixEvent: 'modal',
|
|
15
|
+
placement: 'top',
|
|
16
|
+
template: 'modal/modal.tpl.html',
|
|
17
|
+
contentTemplate: false,
|
|
18
|
+
container: false,
|
|
19
|
+
element: null,
|
|
20
|
+
backdrop: true,
|
|
21
|
+
keyboard: true,
|
|
22
|
+
html: false,
|
|
23
|
+
show: true
|
|
24
|
+
};
|
|
25
|
+
this.$get = [
|
|
26
|
+
'$window',
|
|
27
|
+
'$rootScope',
|
|
28
|
+
'$compile',
|
|
29
|
+
'$q',
|
|
30
|
+
'$templateCache',
|
|
31
|
+
'$http',
|
|
32
|
+
'$animate',
|
|
33
|
+
'$timeout',
|
|
34
|
+
'$sce',
|
|
35
|
+
'dimensions',
|
|
36
|
+
function ($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {
|
|
37
|
+
var forEach = angular.forEach;
|
|
38
|
+
var trim = String.prototype.trim;
|
|
39
|
+
var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;
|
|
40
|
+
var bodyElement = angular.element($window.document.body);
|
|
41
|
+
var htmlReplaceRegExp = /ng-bind="/gi;
|
|
42
|
+
function ModalFactory(config) {
|
|
43
|
+
var $modal = {};
|
|
44
|
+
// Common vars
|
|
45
|
+
var options = $modal.$options = angular.extend({}, defaults, config);
|
|
46
|
+
$modal.$promise = fetchTemplate(options.template);
|
|
47
|
+
var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();
|
|
48
|
+
if (!options.element && !options.container) {
|
|
49
|
+
options.container = 'body';
|
|
50
|
+
}
|
|
51
|
+
// Support scope as string options
|
|
52
|
+
forEach([
|
|
53
|
+
'title',
|
|
54
|
+
'content'
|
|
55
|
+
], function (key) {
|
|
56
|
+
if (options[key])
|
|
57
|
+
scope[key] = options[key]; //$sce.trustAsHtml(options[key]);
|
|
58
|
+
});
|
|
59
|
+
// Provide scope helpers
|
|
60
|
+
scope.$hide = function () {
|
|
61
|
+
scope.$$postDigest(function () {
|
|
62
|
+
$modal.hide();
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
scope.$show = function () {
|
|
66
|
+
scope.$$postDigest(function () {
|
|
67
|
+
$modal.show();
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
scope.$toggle = function () {
|
|
71
|
+
scope.$$postDigest(function () {
|
|
72
|
+
$modal.toggle();
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
// Support contentTemplate option
|
|
76
|
+
if (options.contentTemplate) {
|
|
77
|
+
$modal.$promise = $modal.$promise.then(function (template) {
|
|
78
|
+
var templateEl = angular.element(template);
|
|
79
|
+
return fetchTemplate(options.contentTemplate).then(function (contentTemplate) {
|
|
80
|
+
var contentEl = findElement('[ng-bind="content"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);
|
|
81
|
+
// Drop the default footer as you probably don't want it if you use a custom contentTemplate
|
|
82
|
+
if (!config.template)
|
|
83
|
+
contentEl.next().remove();
|
|
84
|
+
return templateEl[0].outerHTML;
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
// Fetch, compile then initialize modal
|
|
89
|
+
var modalLinker, modalElement;
|
|
90
|
+
var backdropElement = angular.element('<div class="' + options.prefixClass + '-backdrop"/>');
|
|
91
|
+
$modal.$promise.then(function (template) {
|
|
92
|
+
if (angular.isObject(template))
|
|
93
|
+
template = template.data;
|
|
94
|
+
if (options.html)
|
|
95
|
+
template = template.replace(htmlReplaceRegExp, 'ng-bind-html="');
|
|
96
|
+
template = trim.apply(template);
|
|
97
|
+
modalLinker = $compile(template);
|
|
98
|
+
$modal.init();
|
|
99
|
+
});
|
|
100
|
+
$modal.init = function () {
|
|
101
|
+
// Options: show
|
|
102
|
+
if (options.show) {
|
|
103
|
+
scope.$$postDigest(function () {
|
|
104
|
+
$modal.show();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
$modal.destroy = function () {
|
|
109
|
+
// Remove element
|
|
110
|
+
if (modalElement) {
|
|
111
|
+
modalElement.remove();
|
|
112
|
+
modalElement = null;
|
|
113
|
+
}
|
|
114
|
+
if (backdropElement) {
|
|
115
|
+
backdropElement.remove();
|
|
116
|
+
backdropElement = null;
|
|
117
|
+
}
|
|
118
|
+
// Destroy scope
|
|
119
|
+
scope.$destroy();
|
|
120
|
+
};
|
|
121
|
+
$modal.show = function () {
|
|
122
|
+
scope.$emit(options.prefixEvent + '.show.before', $modal);
|
|
123
|
+
var parent = options.container ? findElement(options.container) : null;
|
|
124
|
+
var after = options.container ? null : options.element;
|
|
125
|
+
// Fetch a cloned element linked from template
|
|
126
|
+
modalElement = $modal.$element = modalLinker(scope, function (clonedElement, scope) {
|
|
127
|
+
});
|
|
128
|
+
// Set the initial positioning.
|
|
129
|
+
modalElement.css({ display: 'block' }).addClass(options.placement);
|
|
130
|
+
// Options: animation
|
|
131
|
+
if (options.animation) {
|
|
132
|
+
if (options.backdrop) {
|
|
133
|
+
backdropElement.addClass(options.backdropAnimation);
|
|
134
|
+
}
|
|
135
|
+
modalElement.addClass(options.animation);
|
|
136
|
+
}
|
|
137
|
+
if (options.backdrop) {
|
|
138
|
+
$animate.enter(backdropElement, bodyElement, null, function () {
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
$animate.enter(modalElement, parent, after, function () {
|
|
142
|
+
scope.$emit(options.prefixEvent + '.show', $modal);
|
|
143
|
+
});
|
|
144
|
+
scope.$isShown = true;
|
|
145
|
+
scope.$$phase || scope.$root.$$phase || scope.$digest();
|
|
146
|
+
// Focus once the enter-animation has started
|
|
147
|
+
// Weird PhantomJS bug hack
|
|
148
|
+
var el = modalElement[0];
|
|
149
|
+
requestAnimationFrame(function () {
|
|
150
|
+
el.focus();
|
|
151
|
+
});
|
|
152
|
+
bodyElement.addClass(options.prefixClass + '-open');
|
|
153
|
+
if (options.animation) {
|
|
154
|
+
bodyElement.addClass(options.prefixClass + '-with-' + options.animation);
|
|
155
|
+
}
|
|
156
|
+
// Bind events
|
|
157
|
+
if (options.backdrop) {
|
|
158
|
+
modalElement.on('click', hideOnBackdropClick);
|
|
159
|
+
backdropElement.on('click', hideOnBackdropClick);
|
|
160
|
+
}
|
|
161
|
+
if (options.keyboard) {
|
|
162
|
+
modalElement.on('keyup', $modal.$onKeyUp);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
$modal.hide = function () {
|
|
166
|
+
scope.$emit(options.prefixEvent + '.hide.before', $modal);
|
|
167
|
+
$animate.leave(modalElement, function () {
|
|
168
|
+
scope.$emit(options.prefixEvent + '.hide', $modal);
|
|
169
|
+
bodyElement.removeClass(options.prefixClass + '-open');
|
|
170
|
+
if (options.animation) {
|
|
171
|
+
bodyElement.addClass(options.prefixClass + '-with-' + options.animation);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
if (options.backdrop) {
|
|
175
|
+
$animate.leave(backdropElement, function () {
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
scope.$isShown = false;
|
|
179
|
+
scope.$$phase || scope.$root.$$phase || scope.$digest();
|
|
180
|
+
// Unbind events
|
|
181
|
+
if (options.backdrop) {
|
|
182
|
+
modalElement.off('click', hideOnBackdropClick);
|
|
183
|
+
backdropElement.off('click', hideOnBackdropClick);
|
|
184
|
+
}
|
|
185
|
+
if (options.keyboard) {
|
|
186
|
+
modalElement.off('keyup', $modal.$onKeyUp);
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
$modal.toggle = function () {
|
|
190
|
+
scope.$isShown ? $modal.hide() : $modal.show();
|
|
191
|
+
};
|
|
192
|
+
$modal.focus = function () {
|
|
193
|
+
modalElement[0].focus();
|
|
194
|
+
};
|
|
195
|
+
// Protected methods
|
|
196
|
+
$modal.$onKeyUp = function (evt) {
|
|
197
|
+
evt.which === 27 && $modal.hide();
|
|
198
|
+
};
|
|
199
|
+
// Private methods
|
|
200
|
+
function hideOnBackdropClick(evt) {
|
|
201
|
+
if (evt.target !== evt.currentTarget)
|
|
202
|
+
return;
|
|
203
|
+
options.backdrop === 'static' ? $modal.focus() : $modal.hide();
|
|
204
|
+
}
|
|
205
|
+
return $modal;
|
|
206
|
+
}
|
|
207
|
+
// Helper functions
|
|
208
|
+
function findElement(query, element) {
|
|
209
|
+
return angular.element((element || document).querySelectorAll(query));
|
|
210
|
+
}
|
|
211
|
+
function fetchTemplate(template) {
|
|
212
|
+
return $q.when($templateCache.get(template) || $http.get(template)).then(function (res) {
|
|
213
|
+
if (angular.isObject(res)) {
|
|
214
|
+
$templateCache.put(template, res.data);
|
|
215
|
+
return res.data;
|
|
216
|
+
}
|
|
217
|
+
return res;
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
return ModalFactory;
|
|
221
|
+
}
|
|
222
|
+
];
|
|
223
|
+
}).directive('bsModal', [
|
|
224
|
+
'$window',
|
|
225
|
+
'$location',
|
|
226
|
+
'$sce',
|
|
227
|
+
'$modal',
|
|
228
|
+
function ($window, $location, $sce, $modal) {
|
|
229
|
+
return {
|
|
230
|
+
restrict: 'EAC',
|
|
231
|
+
scope: true,
|
|
232
|
+
link: function postLink(scope, element, attr, transclusion) {
|
|
233
|
+
// Directive options
|
|
234
|
+
var options = {
|
|
235
|
+
scope: scope,
|
|
236
|
+
element: element,
|
|
237
|
+
show: false
|
|
238
|
+
};
|
|
239
|
+
angular.forEach([
|
|
240
|
+
'template',
|
|
241
|
+
'contentTemplate',
|
|
242
|
+
'placement',
|
|
243
|
+
'backdrop',
|
|
244
|
+
'keyboard',
|
|
245
|
+
'html',
|
|
246
|
+
'container',
|
|
247
|
+
'animation'
|
|
248
|
+
], function (key) {
|
|
249
|
+
if (angular.isDefined(attr[key]))
|
|
250
|
+
options[key] = attr[key];
|
|
251
|
+
});
|
|
252
|
+
// Support scope as data-attrs
|
|
253
|
+
angular.forEach([
|
|
254
|
+
'title',
|
|
255
|
+
'content'
|
|
256
|
+
], function (key) {
|
|
257
|
+
attr[key] && attr.$observe(key, function (newValue, oldValue) {
|
|
258
|
+
scope[key] = $sce.trustAsHtml(newValue);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
// Support scope as an object
|
|
262
|
+
attr.bsModal && scope.$watch(attr.bsModal, function (newValue, oldValue) {
|
|
263
|
+
if (angular.isObject(newValue)) {
|
|
264
|
+
angular.extend(scope, newValue);
|
|
265
|
+
} else {
|
|
266
|
+
scope.content = newValue;
|
|
267
|
+
}
|
|
268
|
+
}, true);
|
|
269
|
+
// Initialize modal
|
|
270
|
+
var modal = $modal(options);
|
|
271
|
+
// Trigger
|
|
272
|
+
element.on(attr.trigger || 'click', modal.toggle);
|
|
273
|
+
// Garbage collection
|
|
274
|
+
scope.$on('$destroy', function () {
|
|
275
|
+
modal.destroy();
|
|
276
|
+
options = null;
|
|
277
|
+
modal = null;
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
]);
|