rails-angular-strap 2.2.3 → 2.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 85ff41254a680b072206f2e9d39b9493f90fab36
4
- data.tar.gz: 206de4127b88bb07efb889e0040d640688bd5d66
3
+ metadata.gz: f0cf5183956d9649fbad3fb56bf9daf07aa2adb8
4
+ data.tar.gz: 4ed70de6da32890f92ab44bae0b7fe2a54f121ed
5
5
  SHA512:
6
- metadata.gz: 5c765f02ea1f0ccbcf2fed205d350c8cc81ec81dd78640df1720af28cdd18934efccf0f06f25d1e406452e2d5054b292a912d732434fa628327e6d176cd4a344
7
- data.tar.gz: e3a8312f8f91645d6cbb8334b4de00a04ac18854e62eb9b052a3d478fc2cae7601cb783e27c97f287e9280feda8c78055f10a13f649d950369fee3112f8a34e1
6
+ metadata.gz: a490f753fa7a66d8a55cd6b0ed872f3e41e68e471c3e2899f4e71e50aa8406ebc97689973cc42a290e8d52264b65d1a08d76763768c37e77fc558cdf6b848ebc
7
+ data.tar.gz: d122914afee30813eb486e434e4f69d2a6fe968867083e79a7a7a670c3f904f5f75f88120d6851be8716ebc7c01c66a201aefa9630ba5786eef8095de278d73f
data/README.md CHANGED
@@ -18,4 +18,4 @@ If you desire to require minified AngularStrap files, add the following:
18
18
 
19
19
  ## Versioning
20
20
 
21
- Current version of AngularStrap - 2.2.3
21
+ Current version of AngularStrap - 2.2.4
@@ -1,3 +1,3 @@
1
1
  module AngularStrapRails
2
- VERSION = "2.2.3"
2
+ VERSION = "2.2.4"
3
3
  end
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * angular-strap
3
- * @version v2.2.3 - 2015-05-20
3
+ * @version v2.2.4 - 2015-05-28
4
4
  * @link http://mgcrea.github.io/angular-strap
5
5
  * @author Olivier Louvignes <olivier@mg-crea.com> (https://github.com/mgcrea)
6
6
  * @license MIT License, http://www.opensource.org/licenses/MIT
@@ -182,125 +182,6 @@
182
182
  } ]
183
183
  };
184
184
  });
185
- angular.module('mgcrea.ngStrap.button', []).provider('$button', function() {
186
- var defaults = this.defaults = {
187
- activeClass: 'active',
188
- toggleEvent: 'click'
189
- };
190
- this.$get = function() {
191
- return {
192
- defaults: defaults
193
- };
194
- };
195
- }).directive('bsCheckboxGroup', function() {
196
- return {
197
- restrict: 'A',
198
- require: 'ngModel',
199
- compile: function postLink(element, attr) {
200
- element.attr('data-toggle', 'buttons');
201
- element.removeAttr('ng-model');
202
- var children = element[0].querySelectorAll('input[type="checkbox"]');
203
- angular.forEach(children, function(child) {
204
- var childEl = angular.element(child);
205
- childEl.attr('bs-checkbox', '');
206
- childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));
207
- });
208
- }
209
- };
210
- }).directive('bsCheckbox', [ '$button', '$$rAF', function($button, $$rAF) {
211
- var defaults = $button.defaults;
212
- var constantValueRegExp = /^(true|false|\d+)$/;
213
- return {
214
- restrict: 'A',
215
- require: 'ngModel',
216
- link: function postLink(scope, element, attr, controller) {
217
- var options = defaults;
218
- var isInput = element[0].nodeName === 'INPUT';
219
- var activeElement = isInput ? element.parent() : element;
220
- var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;
221
- if (constantValueRegExp.test(attr.trueValue)) {
222
- trueValue = scope.$eval(attr.trueValue);
223
- }
224
- var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;
225
- if (constantValueRegExp.test(attr.falseValue)) {
226
- falseValue = scope.$eval(attr.falseValue);
227
- }
228
- var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';
229
- if (hasExoticValues) {
230
- controller.$parsers.push(function(viewValue) {
231
- return viewValue ? trueValue : falseValue;
232
- });
233
- controller.$formatters.push(function(modelValue) {
234
- return angular.equals(modelValue, trueValue);
235
- });
236
- scope.$watch(attr.ngModel, function(newValue, oldValue) {
237
- controller.$render();
238
- });
239
- }
240
- controller.$render = function() {
241
- var isActive = angular.equals(controller.$modelValue, trueValue);
242
- $$rAF(function() {
243
- if (isInput) element[0].checked = isActive;
244
- activeElement.toggleClass(options.activeClass, isActive);
245
- });
246
- };
247
- element.bind(options.toggleEvent, function() {
248
- scope.$apply(function() {
249
- if (!isInput) {
250
- controller.$setViewValue(!activeElement.hasClass('active'));
251
- }
252
- if (!hasExoticValues) {
253
- controller.$render();
254
- }
255
- });
256
- });
257
- }
258
- };
259
- } ]).directive('bsRadioGroup', function() {
260
- return {
261
- restrict: 'A',
262
- require: 'ngModel',
263
- compile: function postLink(element, attr) {
264
- element.attr('data-toggle', 'buttons');
265
- element.removeAttr('ng-model');
266
- var children = element[0].querySelectorAll('input[type="radio"]');
267
- angular.forEach(children, function(child) {
268
- angular.element(child).attr('bs-radio', '');
269
- angular.element(child).attr('ng-model', attr.ngModel);
270
- });
271
- }
272
- };
273
- }).directive('bsRadio', [ '$button', '$$rAF', function($button, $$rAF) {
274
- var defaults = $button.defaults;
275
- var constantValueRegExp = /^(true|false|\d+)$/;
276
- return {
277
- restrict: 'A',
278
- require: 'ngModel',
279
- link: function postLink(scope, element, attr, controller) {
280
- var options = defaults;
281
- var isInput = element[0].nodeName === 'INPUT';
282
- var activeElement = isInput ? element.parent() : element;
283
- var value;
284
- attr.$observe('value', function(v) {
285
- value = constantValueRegExp.test(v) ? scope.$eval(v) : v;
286
- controller.$render();
287
- });
288
- controller.$render = function() {
289
- var isActive = angular.equals(controller.$modelValue, value);
290
- $$rAF(function() {
291
- if (isInput) element[0].checked = isActive;
292
- activeElement.toggleClass(options.activeClass, isActive);
293
- });
294
- };
295
- element.bind(options.toggleEvent, function() {
296
- scope.$apply(function() {
297
- controller.$setViewValue(value);
298
- controller.$render();
299
- });
300
- });
301
- }
302
- };
303
- } ]);
304
185
  angular.module('mgcrea.ngStrap.alert', [ 'mgcrea.ngStrap.modal' ]).provider('$alert', function() {
305
186
  var defaults = this.defaults = {
306
187
  animation: 'am-fade',
@@ -1211,7 +1092,7 @@
1211
1092
  $dropdown.show = function() {
1212
1093
  show();
1213
1094
  $timeout(function() {
1214
- options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);
1095
+ options.keyboard && $dropdown.$element && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);
1215
1096
  bodyEl.on('click', onBodyClick);
1216
1097
  }, 0, false);
1217
1098
  parentEl.hasClass('dropdown') && parentEl.addClass('open');
@@ -1219,7 +1100,7 @@
1219
1100
  var hide = $dropdown.hide;
1220
1101
  $dropdown.hide = function() {
1221
1102
  if (!$dropdown.$isShown) return;
1222
- options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);
1103
+ options.keyboard && $dropdown.$element && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);
1223
1104
  bodyEl.off('click', onBodyClick);
1224
1105
  parentEl.hasClass('dropdown') && parentEl.removeClass('open');
1225
1106
  hide();
@@ -1269,6 +1150,125 @@
1269
1150
  }
1270
1151
  };
1271
1152
  } ]);
1153
+ angular.module('mgcrea.ngStrap.button', []).provider('$button', function() {
1154
+ var defaults = this.defaults = {
1155
+ activeClass: 'active',
1156
+ toggleEvent: 'click'
1157
+ };
1158
+ this.$get = function() {
1159
+ return {
1160
+ defaults: defaults
1161
+ };
1162
+ };
1163
+ }).directive('bsCheckboxGroup', function() {
1164
+ return {
1165
+ restrict: 'A',
1166
+ require: 'ngModel',
1167
+ compile: function postLink(element, attr) {
1168
+ element.attr('data-toggle', 'buttons');
1169
+ element.removeAttr('ng-model');
1170
+ var children = element[0].querySelectorAll('input[type="checkbox"]');
1171
+ angular.forEach(children, function(child) {
1172
+ var childEl = angular.element(child);
1173
+ childEl.attr('bs-checkbox', '');
1174
+ childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));
1175
+ });
1176
+ }
1177
+ };
1178
+ }).directive('bsCheckbox', [ '$button', '$$rAF', function($button, $$rAF) {
1179
+ var defaults = $button.defaults;
1180
+ var constantValueRegExp = /^(true|false|\d+)$/;
1181
+ return {
1182
+ restrict: 'A',
1183
+ require: 'ngModel',
1184
+ link: function postLink(scope, element, attr, controller) {
1185
+ var options = defaults;
1186
+ var isInput = element[0].nodeName === 'INPUT';
1187
+ var activeElement = isInput ? element.parent() : element;
1188
+ var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;
1189
+ if (constantValueRegExp.test(attr.trueValue)) {
1190
+ trueValue = scope.$eval(attr.trueValue);
1191
+ }
1192
+ var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;
1193
+ if (constantValueRegExp.test(attr.falseValue)) {
1194
+ falseValue = scope.$eval(attr.falseValue);
1195
+ }
1196
+ var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';
1197
+ if (hasExoticValues) {
1198
+ controller.$parsers.push(function(viewValue) {
1199
+ return viewValue ? trueValue : falseValue;
1200
+ });
1201
+ controller.$formatters.push(function(modelValue) {
1202
+ return angular.equals(modelValue, trueValue);
1203
+ });
1204
+ scope.$watch(attr.ngModel, function(newValue, oldValue) {
1205
+ controller.$render();
1206
+ });
1207
+ }
1208
+ controller.$render = function() {
1209
+ var isActive = angular.equals(controller.$modelValue, trueValue);
1210
+ $$rAF(function() {
1211
+ if (isInput) element[0].checked = isActive;
1212
+ activeElement.toggleClass(options.activeClass, isActive);
1213
+ });
1214
+ };
1215
+ element.bind(options.toggleEvent, function() {
1216
+ scope.$apply(function() {
1217
+ if (!isInput) {
1218
+ controller.$setViewValue(!activeElement.hasClass('active'));
1219
+ }
1220
+ if (!hasExoticValues) {
1221
+ controller.$render();
1222
+ }
1223
+ });
1224
+ });
1225
+ }
1226
+ };
1227
+ } ]).directive('bsRadioGroup', function() {
1228
+ return {
1229
+ restrict: 'A',
1230
+ require: 'ngModel',
1231
+ compile: function postLink(element, attr) {
1232
+ element.attr('data-toggle', 'buttons');
1233
+ element.removeAttr('ng-model');
1234
+ var children = element[0].querySelectorAll('input[type="radio"]');
1235
+ angular.forEach(children, function(child) {
1236
+ angular.element(child).attr('bs-radio', '');
1237
+ angular.element(child).attr('ng-model', attr.ngModel);
1238
+ });
1239
+ }
1240
+ };
1241
+ }).directive('bsRadio', [ '$button', '$$rAF', function($button, $$rAF) {
1242
+ var defaults = $button.defaults;
1243
+ var constantValueRegExp = /^(true|false|\d+)$/;
1244
+ return {
1245
+ restrict: 'A',
1246
+ require: 'ngModel',
1247
+ link: function postLink(scope, element, attr, controller) {
1248
+ var options = defaults;
1249
+ var isInput = element[0].nodeName === 'INPUT';
1250
+ var activeElement = isInput ? element.parent() : element;
1251
+ var value;
1252
+ attr.$observe('value', function(v) {
1253
+ value = constantValueRegExp.test(v) ? scope.$eval(v) : v;
1254
+ controller.$render();
1255
+ });
1256
+ controller.$render = function() {
1257
+ var isActive = angular.equals(controller.$modelValue, value);
1258
+ $$rAF(function() {
1259
+ if (isInput) element[0].checked = isActive;
1260
+ activeElement.toggleClass(options.activeClass, isActive);
1261
+ });
1262
+ };
1263
+ element.bind(options.toggleEvent, function() {
1264
+ scope.$apply(function() {
1265
+ controller.$setViewValue(value);
1266
+ controller.$render();
1267
+ });
1268
+ });
1269
+ }
1270
+ };
1271
+ } ]);
1272
1272
  angular.module('mgcrea.ngStrap.helpers.dateFormatter', []).service('$dateFormatter', [ '$locale', 'dateFilter', function($locale, dateFilter) {
1273
1273
  this.getDefaultLocale = function() {
1274
1274
  return $locale.id;
@@ -1890,8 +1890,11 @@
1890
1890
  if (options.backdrop) {
1891
1891
  $animate.enter(backdropElement, bodyElement, null);
1892
1892
  }
1893
- var promise = $animate.enter(modalElement, parent, after, enterAnimateCallback);
1894
- if (promise && promise.then) promise.then(enterAnimateCallback);
1893
+ if (angular.version.minor <= 2) {
1894
+ $animate.enter(modalElement, parent, after, enterAnimateCallback);
1895
+ } else {
1896
+ $animate.enter(modalElement, parent, after).then(enterAnimateCallback);
1897
+ }
1895
1898
  $modal.$isShown = scope.$isShown = true;
1896
1899
  safeDigest(scope);
1897
1900
  var el = modalElement[0];
@@ -1919,8 +1922,11 @@
1919
1922
  if (scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {
1920
1923
  return;
1921
1924
  }
1922
- var promise = $animate.leave(modalElement, leaveAnimateCallback);
1923
- if (promise && promise.then) promise.then(leaveAnimateCallback);
1925
+ if (angular.version.minor <= 2) {
1926
+ $animate.leave(modalElement, leaveAnimateCallback);
1927
+ } else {
1928
+ $animate.leave(modalElement).then(leaveAnimateCallback);
1929
+ }
1924
1930
  if (options.backdrop) {
1925
1931
  $animate.leave(backdropElement);
1926
1932
  }
@@ -2397,7 +2403,9 @@
2397
2403
  $select.activate = function(index) {
2398
2404
  if (options.multiple) {
2399
2405
  $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);
2400
- if (options.sort) scope.$activeIndex.sort();
2406
+ if (options.sort) scope.$activeIndex.sort(function(a, b) {
2407
+ return a - b;
2408
+ });
2401
2409
  } else {
2402
2410
  scope.$activeIndex = index;
2403
2411
  }
@@ -3010,18 +3018,18 @@
3010
3018
  $timepicker.show = function() {
3011
3019
  _show();
3012
3020
  $timeout(function() {
3013
- $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);
3021
+ $timepicker.$element && $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);
3014
3022
  if (options.keyboard) {
3015
- element.on('keydown', $timepicker.$onKeyDown);
3023
+ element && element.on('keydown', $timepicker.$onKeyDown);
3016
3024
  }
3017
3025
  }, 0, false);
3018
3026
  };
3019
3027
  var _hide = $timepicker.hide;
3020
3028
  $timepicker.hide = function(blur) {
3021
3029
  if (!$timepicker.$isShown) return;
3022
- $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);
3030
+ $timepicker.$element && $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);
3023
3031
  if (options.keyboard) {
3024
- element.off('keydown', $timepicker.$onKeyDown);
3032
+ element && element.off('keydown', $timepicker.$onKeyDown);
3025
3033
  }
3026
3034
  _hide(blur);
3027
3035
  };
@@ -3306,8 +3314,11 @@
3306
3314
  $tooltip.$isShown = scope.$isShown = true;
3307
3315
  safeDigest(scope);
3308
3316
  $tooltip.$applyPlacement();
3309
- var promise = $animate.enter(tipElement, parent, after, enterAnimateCallback);
3310
- if (promise && promise.then) promise.then(enterAnimateCallback);
3317
+ if (angular.version.minor <= 2) {
3318
+ $animate.enter(tipElement, parent, after, enterAnimateCallback);
3319
+ } else {
3320
+ $animate.enter(tipElement, parent, after).then(enterAnimateCallback);
3321
+ }
3311
3322
  safeDigest(scope);
3312
3323
  $$rAF(function() {
3313
3324
  if (tipElement) tipElement.css({
@@ -3346,8 +3357,11 @@
3346
3357
  scope.$emit(options.prefixEvent + '.hide.before', $tooltip);
3347
3358
  _blur = blur;
3348
3359
  _tipToHide = tipElement;
3349
- var promise = $animate.leave(tipElement, leaveAnimateCallback);
3350
- if (promise && promise.then) promise.then(leaveAnimateCallback);
3360
+ if (angular.version.minor <= 2) {
3361
+ $animate.leave(tipElement, leaveAnimateCallback);
3362
+ } else {
3363
+ $animate.leave(tipElement).then(leaveAnimateCallback);
3364
+ }
3351
3365
  $tooltip.$isShown = scope.$isShown = false;
3352
3366
  safeDigest(scope);
3353
3367
  if (options.keyboard && tipElement !== null) {
@@ -3824,17 +3838,17 @@
3824
3838
  $typeahead.show = function() {
3825
3839
  show();
3826
3840
  $timeout(function() {
3827
- $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);
3841
+ $typeahead.$element && $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);
3828
3842
  if (options.keyboard) {
3829
- element.on('keydown', $typeahead.$onKeyDown);
3843
+ element && element.on('keydown', $typeahead.$onKeyDown);
3830
3844
  }
3831
3845
  }, 0, false);
3832
3846
  };
3833
3847
  var hide = $typeahead.hide;
3834
3848
  $typeahead.hide = function() {
3835
- $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);
3849
+ $typeahead.$element && $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);
3836
3850
  if (options.keyboard) {
3837
- element.off('keydown', $typeahead.$onKeyDown);
3851
+ element && element.off('keydown', $typeahead.$onKeyDown);
3838
3852
  }
3839
3853
  if (!options.autoSelect) $typeahead.activate(-1);
3840
3854
  hide();
@@ -3896,7 +3910,11 @@
3896
3910
  });
3897
3911
  controller.$formatters.push(function(modelValue) {
3898
3912
  var displayValue = parsedOptions.displayValue(modelValue);
3899
- return displayValue === undefined ? '' : displayValue;
3913
+ if (displayValue) return displayValue;
3914
+ if (modelValue && typeof modelValue !== 'object') {
3915
+ return modelValue;
3916
+ }
3917
+ return '';
3900
3918
  });
3901
3919
  controller.$render = function() {
3902
3920
  if (controller.$isEmpty(controller.$viewValue)) return element.val('');
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * angular-strap
3
- * @version v2.2.3 - 2015-05-20
3
+ * @version v2.2.4 - 2015-05-28
4
4
  * @link http://mgcrea.github.io/angular-strap
5
5
  * @author Olivier Louvignes <olivier@mg-crea.com> (https://github.com/mgcrea)
6
6
  * @license MIT License, http://www.opensource.org/licenses/MIT
7
7
  */
8
- !function(e,t,n){'use strict';angular.module('mgcrea.ngStrap',['mgcrea.ngStrap.modal','mgcrea.ngStrap.aside','mgcrea.ngStrap.alert','mgcrea.ngStrap.button','mgcrea.ngStrap.select','mgcrea.ngStrap.datepicker','mgcrea.ngStrap.timepicker','mgcrea.ngStrap.navbar','mgcrea.ngStrap.tooltip','mgcrea.ngStrap.popover','mgcrea.ngStrap.dropdown','mgcrea.ngStrap.typeahead','mgcrea.ngStrap.scrollspy','mgcrea.ngStrap.affix','mgcrea.ngStrap.tab','mgcrea.ngStrap.collapse']),angular.module('mgcrea.ngStrap.affix',['mgcrea.ngStrap.helpers.dimensions','mgcrea.ngStrap.helpers.debounce']).provider('$affix',function(){var e=this.defaults={offsetTop:'auto',inlineStyles:!0};this.$get=['$window','debounce','dimensions',function(t,n,a){function o(o,s){function l(e,t,n){var a=u(),o=c();return v>=a?'top':null!==e&&a+e<=t.top?'middle':null!==w&&t.top+n+$>=o-w?'bottom':'middle'}function u(){return p[0]===t?t.pageYOffset:p[0].scrollTop}function c(){return p[0]===t?t.document.body.scrollHeight:p[0].scrollHeight}var d={},f=angular.extend({},e,s),p=f.target,g='affix affix-top affix-bottom',m=!1,$=0,h=0,v=0,w=0,y=null,b=null,D=o.parent();if(f.offsetParent)if(f.offsetParent.match(/^\d+$/))for(var k=0;k<1*f.offsetParent-1;k++)D=D.parent();else D=angular.element(f.offsetParent);return d.init=function(){this.$parseOffsets(),h=a.offset(o[0]).top+$,m=!o[0].style.width,p.on('scroll',this.checkPosition),p.on('click',this.checkPositionWithEventLoop),r.on('resize',this.$debouncedOnResize),this.checkPosition(),this.checkPositionWithEventLoop()},d.destroy=function(){p.off('scroll',this.checkPosition),p.off('click',this.checkPositionWithEventLoop),r.off('resize',this.$debouncedOnResize)},d.checkPositionWithEventLoop=function(){setTimeout(d.checkPosition,1)},d.checkPosition=function(){var e=u(),t=a.offset(o[0]),n=a.height(o[0]),r=l(b,t,n);y!==r&&(y=r,o.removeClass(g).addClass('affix'+('middle'!==r?'-'+r:'')),'top'===r?(b=null,m&&o.css('width',''),f.inlineStyles&&(o.css('position',f.offsetParent?'':'relative'),o.css('top',''))):'bottom'===r?(b=f.offsetUnpin?-(1*f.offsetUnpin):t.top-e,m&&o.css('width',''),f.inlineStyles&&(o.css('position',f.offsetParent?'':'relative'),o.css('top',f.offsetParent?'':i[0].offsetHeight-w-n-h+'px'))):(b=null,m&&o.css('width',o[0].offsetWidth+'px'),f.inlineStyles&&(o.css('position','fixed'),o.css('top',$+'px'))))},d.$onResize=function(){d.$parseOffsets(),d.checkPosition()},d.$debouncedOnResize=n(d.$onResize,50),d.$parseOffsets=function(){var e=o.css('position');f.inlineStyles&&o.css('position',f.offsetParent?'':'relative'),f.offsetTop&&('auto'===f.offsetTop&&(f.offsetTop='+0'),f.offsetTop.match(/^[-+]\d+$/)?($=1*-f.offsetTop,v=f.offsetParent?a.offset(D[0]).top+1*f.offsetTop:a.offset(o[0]).top-a.css(o[0],'marginTop',!0)+1*f.offsetTop):v=1*f.offsetTop),f.offsetBottom&&(w=f.offsetParent&&f.offsetBottom.match(/^[-+]\d+$/)?c()-(a.offset(D[0]).top+a.height(D[0]))+1*f.offsetBottom+1:1*f.offsetBottom),f.inlineStyles&&o.css('position',e)},d.init(),d}var i=angular.element(t.document.body),r=angular.element(t);return o}]}).directive('bsAffix',['$affix','$window',function(e,t){return{restrict:'EAC',require:'^?bsAffixTarget',link:function(n,a,o,i){var r={scope:n,target:i?i.$element:angular.element(t)};angular.forEach(['offsetTop','offsetBottom','offsetParent','offsetUnpin','inlineStyles'],function(e){if(angular.isDefined(o[e])){var t=o[e];/true/i.test(t)&&(t=!0),/false/i.test(t)&&(t=!1),r[e]=t}});var s=e(a,r);n.$on('$destroy',function(){s&&s.destroy(),r=null,s=null})}}}]).directive('bsAffixTarget',function(){return{controller:['$element',function(e){this.$element=e}]}}),angular.module('mgcrea.ngStrap.button',[]).provider('$button',function(){var e=this.defaults={activeClass:'active',toggleEvent:'click'};this.$get=function(){return{defaults:e}}}).directive('bsCheckboxGroup',function(){return{restrict:'A',require:'ngModel',compile:function(e,t){e.attr('data-toggle','buttons'),e.removeAttr('ng-model');var n=e[0].querySelectorAll('input[type="checkbox"]');angular.forEach(n,function(e){var n=angular.element(e);n.attr('bs-checkbox',''),n.attr('ng-model',t.ngModel+'.'+n.attr('value'))})}}}).directive('bsCheckbox',['$button','$$rAF',function(e,t){var n=e.defaults,a=/^(true|false|\d+)$/;return{restrict:'A',require:'ngModel',link:function(e,o,i,r){var s=n,l='INPUT'===o[0].nodeName,u=l?o.parent():o,c=angular.isDefined(i.trueValue)?i.trueValue:!0;a.test(i.trueValue)&&(c=e.$eval(i.trueValue));var d=angular.isDefined(i.falseValue)?i.falseValue:!1;a.test(i.falseValue)&&(d=e.$eval(i.falseValue));var f='boolean'!=typeof c||'boolean'!=typeof d;f&&(r.$parsers.push(function(e){return e?c:d}),r.$formatters.push(function(e){return angular.equals(e,c)}),e.$watch(i.ngModel,function(e,t){r.$render()})),r.$render=function(){var e=angular.equals(r.$modelValue,c);t(function(){l&&(o[0].checked=e),u.toggleClass(s.activeClass,e)})},o.bind(s.toggleEvent,function(){e.$apply(function(){l||r.$setViewValue(!u.hasClass('active')),f||r.$render()})})}}}]).directive('bsRadioGroup',function(){return{restrict:'A',require:'ngModel',compile:function(e,t){e.attr('data-toggle','buttons'),e.removeAttr('ng-model');var n=e[0].querySelectorAll('input[type="radio"]');angular.forEach(n,function(e){angular.element(e).attr('bs-radio',''),angular.element(e).attr('ng-model',t.ngModel)})}}}).directive('bsRadio',['$button','$$rAF',function(e,t){var n=e.defaults,a=/^(true|false|\d+)$/;return{restrict:'A',require:'ngModel',link:function(e,o,i,r){var s,l=n,u='INPUT'===o[0].nodeName,c=u?o.parent():o;i.$observe('value',function(t){s=a.test(t)?e.$eval(t):t,r.$render()}),r.$render=function(){var e=angular.equals(r.$modelValue,s);t(function(){u&&(o[0].checked=e),c.toggleClass(l.activeClass,e)})},o.bind(l.toggleEvent,function(){e.$apply(function(){r.$setViewValue(s),r.$render()})})}}}]),angular.module('mgcrea.ngStrap.alert',['mgcrea.ngStrap.modal']).provider('$alert',function(){var e=this.defaults={animation:'am-fade',prefixClass:'alert',prefixEvent:'alert',placement:null,template:'alert/alert.tpl.html',container:!1,element:null,backdrop:!1,keyboard:!0,show:!0,duration:!1,type:!1,dismissable:!0};this.$get=['$modal','$timeout',function(t,n){function a(a){var o={},i=angular.extend({},e,a);o=t(i),o.$scope.dismissable=!!i.dismissable,i.type&&(o.$scope.type=i.type);var r=o.show;return i.duration&&(o.show=function(){r(),n(function(){o.hide()},1e3*i.duration)}),o}return a}]}).directive('bsAlert',['$window','$sce','$alert',function(e,t,n){e.requestAnimationFrame||e.setTimeout;return{restrict:'EAC',scope:!0,link:function(e,a,o,i){var r={scope:e,element:a,show:!1};angular.forEach(['template','placement','keyboard','html','container','animation','duration','dismissable'],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var s=/^(false|0|)$/i;angular.forEach(['keyboard','html','container','dismissable'],function(e){angular.isDefined(o[e])&&s.test(o[e])&&(r[e]=!1)}),e.hasOwnProperty('title')||(e.title=''),angular.forEach(['title','content','type'],function(n){o[n]&&o.$observe(n,function(a,o){e[n]=t.trustAsHtml(a)})}),o.bsAlert&&e.$watch(o.bsAlert,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var l=n(r);a.on(o.trigger||'click',l.toggle),e.$on('$destroy',function(){l&&l.destroy(),r=null,l=null})}}}]),angular.module('mgcrea.ngStrap.aside',['mgcrea.ngStrap.modal']).provider('$aside',function(){var e=this.defaults={animation:'am-fade-and-slide-right',prefixClass:'aside',prefixEvent:'aside',placement:'right',template:'aside/aside.tpl.html',contentTemplate:!1,container:!1,element:null,backdrop:!0,keyboard:!0,html:!1,show:!0};this.$get=['$modal',function(t){function n(n){var a={},o=angular.extend({},e,n);return a=t(o)}return n}]}).directive('bsAside',['$window','$sce','$aside',function(e,t,n){e.requestAnimationFrame||e.setTimeout;return{restrict:'EAC',scope:!0,link:function(e,a,o,i){var r={scope:e,element:a,show:!1};angular.forEach(['template','contentTemplate','placement','backdrop','keyboard','html','container','animation'],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var s=/^(false|0|)$/i;angular.forEach(['backdrop','keyboard','html','container'],function(e){angular.isDefined(o[e])&&s.test(o[e])&&(r[e]=!1)}),angular.forEach(['title','content'],function(n){o[n]&&o.$observe(n,function(a,o){e[n]=t.trustAsHtml(a)})}),o.bsAside&&e.$watch(o.bsAside,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var l=n(r);a.on(o.trigger||'click',l.toggle),e.$on('$destroy',function(){l&&l.destroy(),r=null,l=null})}}}]),angular.module('mgcrea.ngStrap.collapse',[]).provider('$collapse',function(){var e=this.defaults={animation:'am-collapse',disallowToggle:!1,activeClass:'in',startCollapsed:!1,allowMultiple:!1},t=this.controller=function(t,n,a){function o(e){for(var t=l.$targets.$active,n=0;n<t.length;n++)e<t[n]&&(t[n]=t[n]-1),t[n]===l.$targets.length&&(t[n]=l.$targets.length-1)}function i(e){var t=l.$targets.$active;return-1===t.indexOf(e)?!1:!0}function r(e){var t=l.$targets.$active.indexOf(e);-1!==t&&l.$targets.$active.splice(t,1)}function s(e){l.$options.allowMultiple||l.$targets.$active.splice(0,1),-1===l.$targets.$active.indexOf(e)&&l.$targets.$active.push(e)}var l=this;l.$options=angular.copy(e),angular.forEach(['animation','disallowToggle','activeClass','startCollapsed','allowMultiple'],function(e){angular.isDefined(a[e])&&(l.$options[e]=a[e])});var u=/^(false|0|)$/i;angular.forEach(['disallowToggle','startCollapsed','allowMultiple'],function(e){angular.isDefined(a[e])&&u.test(a[e])&&(l.$options[e]=!1)}),l.$toggles=[],l.$targets=[],l.$viewChangeListeners=[],l.$registerToggle=function(e){l.$toggles.push(e)},l.$registerTarget=function(e){l.$targets.push(e)},l.$unregisterToggle=function(e){var t=l.$toggles.indexOf(e);l.$toggles.splice(t,1)},l.$unregisterTarget=function(e){var t=l.$targets.indexOf(e);l.$targets.splice(t,1),l.$options.allowMultiple&&r(e),o(t),l.$viewChangeListeners.forEach(function(e){e()})},l.$targets.$active=l.$options.startCollapsed?[]:[0],l.$setActive=t.$setActive=function(e){angular.isArray(e)?l.$targets.$active=e:l.$options.disallowToggle?s(e):i(e)?r(e):s(e),l.$viewChangeListeners.forEach(function(e){e()})},l.$activeIndexes=function(){return l.$options.allowMultiple?l.$targets.$active:1===l.$targets.$active.length?l.$targets.$active[0]:-1}};this.$get=function(){var n={};return n.defaults=e,n.controller=t,n}}).directive('bsCollapse',['$window','$animate','$collapse',function(e,t,n){n.defaults;return{require:['?ngModel','bsCollapse'],controller:['$scope','$element','$attrs',n.controller],link:function(e,t,n,a){var o=a[0],i=a[1];o&&(i.$viewChangeListeners.push(function(){o.$setViewValue(i.$activeIndexes())}),o.$formatters.push(function(e){if(angular.isArray(e))i.$setActive(e);else{var t=i.$activeIndexes();angular.isArray(t)?-1===t.indexOf(1*e)&&i.$setActive(1*e):t!==1*e&&i.$setActive(1*e)}return e}))}}}]).directive('bsCollapseToggle',function(){return{require:['^?ngModel','^bsCollapse'],link:function(e,t,n,a){var o=(a[0],a[1]);t.attr('data-toggle','collapse'),o.$registerToggle(t),e.$on('$destroy',function(){o.$unregisterToggle(t)}),t.on('click',function(){var a=n.bsCollapseToggle||o.$toggles.indexOf(t);o.$setActive(1*a),e.$apply()})}}}).directive('bsCollapseTarget',['$animate',function(e){return{require:['^?ngModel','^bsCollapse'],link:function(t,n,a,o){function i(){var t=r.$targets.indexOf(n),a=r.$activeIndexes(),o='removeClass';angular.isArray(a)?-1!==a.indexOf(t)&&(o='addClass'):t===a&&(o='addClass'),e[o](n,r.$options.activeClass)}var r=(o[0],o[1]);n.addClass('collapse'),r.$options.animation&&n.addClass(r.$options.animation),r.$registerTarget(n),t.$on('$destroy',function(){r.$unregisterTarget(n)}),r.$viewChangeListeners.push(function(){i()}),i()}}}]),angular.module('mgcrea.ngStrap.datepicker',['mgcrea.ngStrap.helpers.dateParser','mgcrea.ngStrap.helpers.dateFormatter','mgcrea.ngStrap.tooltip']).provider('$datepicker',function(){var e=this.defaults={animation:'am-fade',prefixClass:'datepicker',placement:'bottom-left',template:'datepicker/datepicker.tpl.html',trigger:'focus',container:!1,keyboard:!0,html:!1,delay:0,useNative:!1,dateType:'date',dateFormat:'shortDate',timezone:null,modelDateFormat:null,dayFormat:'dd',monthFormat:'MMM',yearFormat:'yyyy',monthTitleFormat:'MMMM yyyy',yearTitleFormat:'yyyy',strictFormat:!1,autoclose:!1,minDate:-(1/0),maxDate:+(1/0),startView:0,minView:0,startWeek:0,daysOfWeekDisabled:'',iconLeft:'glyphicon glyphicon-chevron-left',iconRight:'glyphicon glyphicon-chevron-right'};this.$get=['$window','$document','$rootScope','$sce','$dateFormatter','datepickerViews','$tooltip','$timeout',function(t,n,a,o,i,r,s,l){function u(t,n,a){function o(e){e.selected=u.$isSelected(e.date)}function i(){t[0].focus()}var u=s(t,angular.extend({},e,a)),f=a.scope,p=u.$options,g=u.$scope;p.startView&&(p.startView-=p.minView);var m=r(u);u.$views=m.views;var $=m.viewDate;g.$mode=p.startView,g.$iconLeft=p.iconLeft,g.$iconRight=p.iconRight;var h=u.$views[g.$mode];g.$select=function(e){u.select(e)},g.$selectPane=function(e){u.$selectPane(e)},g.$toggleMode=function(){u.setMode((g.$mode+1)%u.$views.length)},u.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())&&(u.$date=e,h.update.call(h,e)),u.$build(!0)},u.updateDisabledDates=function(e){p.disabledDateRanges=e;for(var t=0,n=g.rows.length;n>t;t++)angular.forEach(g.rows[t],u.$setDisabledEl)},u.select=function(e,t){angular.isDate(n.$dateValue)||(n.$dateValue=new Date(e)),!g.$mode||t?(n.$setViewValue(angular.copy(e)),n.$render(),p.autoclose&&!t&&l(function(){u.hide(!0)})):(angular.extend($,{year:e.getFullYear(),month:e.getMonth(),date:e.getDate()}),u.setMode(g.$mode-1),u.$build())},u.setMode=function(e){g.$mode=e,h=u.$views[g.$mode],u.$build()},u.$build=function(e){e===!0&&h.built||(e!==!1||h.built)&&h.build.call(h)},u.$updateSelected=function(){for(var e=0,t=g.rows.length;t>e;e++)angular.forEach(g.rows[e],o)},u.$isSelected=function(e){return h.isSelected(e)},u.$setDisabledEl=function(e){e.disabled=h.isDisabled(e.date)},u.$selectPane=function(e){var t=h.steps,n=new Date(Date.UTC($.year+(t.year||0)*e,$.month+(t.month||0)*e,1));angular.extend($,{year:n.getUTCFullYear(),month:n.getUTCMonth(),date:n.getUTCDate()}),u.$build()},u.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),d){var t=angular.element(e.target);'button'!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler('click')}},u.$onKeyDown=function(e){if(/(38|37|39|40|13)/.test(e.keyCode)&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),e.stopPropagation(),13===e.keyCode)return g.$mode?g.$apply(function(){u.setMode(g.$mode-1)}):u.hide(!0);h.onKeyDown(e),f.$digest()}};var v=u.init;u.init=function(){return c&&p.useNative?(t.prop('type','date'),void t.css('-webkit-appearance','textfield')):(d&&(t.prop('type','text'),t.attr('readonly','true'),t.on('click',i)),void v())};var w=u.destroy;u.destroy=function(){c&&p.useNative&&t.off('click',i),w()};var y=u.show;u.show=function(){y(),l(function(){u.$isShown&&(u.$element.on(d?'touchstart':'mousedown',u.$onMouseDown),p.keyboard&&t.on('keydown',u.$onKeyDown))},0,!1)};var b=u.hide;return u.hide=function(e){u.$isShown&&(u.$element.off(d?'touchstart':'mousedown',u.$onMouseDown),p.keyboard&&t.off('keydown',u.$onKeyDown),b(e))},u}var c=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),d='createTouch'in t.document&&c;return e.lang||(e.lang=i.getDefaultLocale()),u.defaults=e,u}]}).directive('bsDatepicker',['$window','$parse','$q','$dateFormatter','$dateParser','$datepicker',function(e,t,n,a,o,i){var r=(i.defaults,/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent));return{restrict:'EAC',require:'ngModel',link:function(e,t,n,s){function l(e){return e&&e.length?e:null}function u(e){if(angular.isDate(e)){var t=isNaN(p.$options.minDate)||e.getTime()>=p.$options.minDate,n=isNaN(p.$options.maxDate)||e.getTime()<=p.$options.maxDate,a=t&&n;s.$setValidity('date',a),s.$setValidity('min',t),s.$setValidity('max',n),a&&(s.$dateValue=e)}}function c(){return!s.$dateValue||isNaN(s.$dateValue.getTime())?'':m(s.$dateValue,d.dateFormat)}var d={scope:e,controller:s};angular.forEach(['placement','container','delay','trigger','html','animation','template','autoclose','dateType','dateFormat','timezone','modelDateFormat','dayFormat','strictFormat','startWeek','startDate','useNative','lang','startView','minView','iconLeft','iconRight','daysOfWeekDisabled','id','prefixClass','prefixEvent'],function(e){angular.isDefined(n[e])&&(d[e]=n[e])});var f=/^(false|0|)$/i;angular.forEach(['html','container','autoclose','useNative'],function(e){angular.isDefined(n[e])&&f.test(n[e])&&(d[e]=!1)}),n.bsShow&&e.$watch(n.bsShow,function(e,t){p&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(datepicker),?/i)),e===!0?p.show():p.hide())});var p=i(t,s,d);d=p.$options,r&&d.useNative&&(d.dateFormat='yyyy-MM-dd');var g=d.lang,m=function(e,t){return a.formatDate(e,t,g)},$=o({format:d.dateFormat,lang:g,strict:d.strictFormat});angular.forEach(['minDate','maxDate'],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){p.$options[e]=$.getDateForAttribute(e,t),!isNaN(p.$options[e])&&p.$build(!1),u(s.$dateValue)})}),e.$watch(n.ngModel,function(e,t){p.update(s.$dateValue)},!0),angular.isDefined(n.disabledDates)&&e.$watch(n.disabledDates,function(e,t){e=l(e),t=l(t),e&&p.updateDisabledDates(e)}),s.$parsers.unshift(function(e){var t;if(!e)return s.$setValidity('date',!0),null;var n=$.parse(e,s.$dateValue);return!n||isNaN(n.getTime())?void s.$setValidity('date',!1):(u(n),'string'===d.dateType?(t=$.timezoneOffsetAdjust(n,d.timezone,!0),m(t,d.modelDateFormat||d.dateFormat)):(t=$.timezoneOffsetAdjust(s.$dateValue,d.timezone,!0),'number'===d.dateType?t.getTime():'unix'===d.dateType?t.getTime()/1e3:'iso'===d.dateType?t.toISOString():new Date(t)))}),s.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:'string'===d.dateType?$.parse(e,null,d.modelDateFormat):new Date('unix'===d.dateType?1e3*e:e),s.$dateValue=$.timezoneOffsetAdjust(t,d.timezone),c()}),s.$render=function(){t.val(c())},e.$on('$destroy',function(){p&&p.destroy(),d=null,p=null})}}}]).provider('datepickerViews',function(){function e(e,t){for(var n=[];e.length>0;)n.push(e.splice(0,t));return n}function t(e,t){return(e%t+t)%t}this.defaults={dayFormat:'dd',daySplit:7};this.$get=['$dateFormatter','$dateParser','$sce',function(n,a,o){return function(i){var r=i.$scope,s=i.$options,l=s.lang,u=function(e,t){return n.formatDate(e,t,l)},c=a({format:s.dateFormat,lang:l,strict:s.strictFormat}),d=n.weekdaysShort(l),f=d.slice(s.startWeek).concat(d.slice(0,s.startWeek)),p=o.trustAsHtml('<th class="dow text-center">'+f.join('</th><th class="dow text-center">')+'</th>'),g=i.$date||(s.startDate?c.getDateForAttribute('startDate',s.startDate):new Date),m={year:g.getFullYear(),month:g.getMonth(),date:g.getDate()},$=[{format:s.dayFormat,split:7,steps:{month:1},update:function(e,t){!this.built||t||e.getFullYear()!==m.year||e.getMonth()!==m.month?(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build()):(e.getDate()!==m.date||1===e.getDate())&&(m.date=i.$date.getDate(),i.$updateSelected())},build:function(){var n=new Date(m.year,m.month,1),a=n.getTimezoneOffset(),o=new Date(+n-864e5*t(n.getDay()-s.startWeek,7)),l=o.getTimezoneOffset(),d=c.timezoneOffsetAdjust(new Date,s.timezone).toDateString();l!==a&&(o=new Date(+o+6e4*(l-a)));for(var f,g=[],$=0;42>$;$++)f=c.daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth(),o.getDate()+$)),g.push({date:f,isToday:f.toDateString()===d,label:u(f,this.format),selected:i.$date&&this.isSelected(f),muted:f.getMonth()!==m.month,disabled:this.isDisabled(f)});r.title=u(n,s.monthTitleFormat),r.showLabels=!0,r.labels=p,r.rows=e(g,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()&&e.getMonth()===i.$date.getMonth()&&e.getDate()===i.$date.getDate()},isDisabled:function(e){var t=e.getTime();if(t<s.minDate||t>s.maxDate)return!0;if(-1!==s.daysOfWeekDisabled.indexOf(e.getDay()))return!0;if(s.disabledDateRanges)for(var n=0;n<s.disabledDateRanges.length;n++)if(t>=s.disabledDateRanges[n].start&&t<=s.disabledDateRanges[n].end)return!0;return!1},onKeyDown:function(e){if(i.$date){var t,n=i.$date.getTime();37===e.keyCode?t=new Date(n-864e5):38===e.keyCode?t=new Date(n-6048e5):39===e.keyCode?t=new Date(n+864e5):40===e.keyCode&&(t=new Date(n+6048e5)),this.isDisabled(t)||i.select(t,!0)}}},{name:'month',format:s.monthFormat,split:4,steps:{year:1},update:function(e,t){this.built&&e.getFullYear()===m.year?e.getMonth()!==m.month&&(angular.extend(m,{month:i.$date.getMonth(),date:i.$date.getDate()}),i.$updateSelected()):(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build())},build:function(){for(var t,n=(new Date(m.year,0,1),[]),a=0;12>a;a++)t=new Date(m.year,a,1),n.push({date:t,label:u(t,this.format),selected:i.$isSelected(t),disabled:this.isDisabled(t)});r.title=u(t,s.yearTitleFormat),r.showLabels=!1,r.rows=e(n,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()&&e.getMonth()===i.$date.getMonth()},isDisabled:function(e){var t=+new Date(e.getFullYear(),e.getMonth()+1,0);return t<s.minDate||e.getTime()>s.maxDate},onKeyDown:function(e){if(i.$date){var t=i.$date.getMonth(),n=new Date(i.$date);37===e.keyCode?n.setMonth(t-1):38===e.keyCode?n.setMonth(t-4):39===e.keyCode?n.setMonth(t+1):40===e.keyCode&&n.setMonth(t+4),this.isDisabled(n)||i.select(n,!0)}}},{name:'year',format:s.yearFormat,split:4,steps:{year:12},update:function(e,t){!this.built||t||parseInt(e.getFullYear()/20,10)!==parseInt(m.year/20,10)?(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build()):e.getFullYear()!==m.year&&(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$updateSelected())},build:function(){for(var t,n=m.year-m.year%(3*this.split),a=[],o=0;12>o;o++)t=new Date(n+o,0,1),a.push({date:t,label:u(t,this.format),selected:i.$isSelected(t),disabled:this.isDisabled(t)});r.title=a[0].label+'-'+a[a.length-1].label,r.showLabels=!1,r.rows=e(a,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()},isDisabled:function(e){var t=+new Date(e.getFullYear()+1,0,0);return t<s.minDate||e.getTime()>s.maxDate},onKeyDown:function(e){if(i.$date){var t=i.$date.getFullYear(),n=new Date(i.$date);37===e.keyCode?n.setYear(t-1):38===e.keyCode?n.setYear(t-4):39===e.keyCode?n.setYear(t+1):40===e.keyCode&&n.setYear(t+4),this.isDisabled(n)||i.select(n,!0)}}}];return{views:s.minView?Array.prototype.slice.call($,s.minView):$,viewDate:m}}}]}),angular.module('mgcrea.ngStrap.dropdown',['mgcrea.ngStrap.tooltip']).provider('$dropdown',function(){var e=this.defaults={animation:'am-fade',prefixClass:'dropdown',prefixEvent:'dropdown',placement:'bottom-left',template:'dropdown/dropdown.tpl.html',trigger:'click',container:!1,keyboard:!0,html:!1,delay:0};this.$get=['$window','$rootScope','$tooltip','$timeout',function(t,n,a,o){function i(t,i){function l(e){return e.target!==t[0]?e.target!==t[0]&&u.hide():void 0}{var u={},c=angular.extend({},e,i);u.$scope=c.scope&&c.scope.$new()||n.$new()}u=a(t,c);var d=t.parent();u.$onKeyDown=function(e){if(/(38|40)/.test(e.keyCode)){e.preventDefault(),e.stopPropagation();var t=angular.element(u.$element[0].querySelectorAll('li:not(.divider) a'));if(t.length){var n;angular.forEach(t,function(e,t){s&&s.call(e,':focus')&&(n=t)}),38===e.keyCode&&n>0?n--:40===e.keyCode&&n<t.length-1?n++:angular.isUndefined(n)&&(n=0),t.eq(n)[0].focus()}}};var f=u.show;u.show=function(){f(),o(function(){c.keyboard&&u.$element.on('keydown',u.$onKeyDown),r.on('click',l)},0,!1),d.hasClass('dropdown')&&d.addClass('open')};var p=u.hide;u.hide=function(){u.$isShown&&(c.keyboard&&u.$element.off('keydown',u.$onKeyDown),r.off('click',l),d.hasClass('dropdown')&&d.removeClass('open'),p())};var g=u.destroy;return u.destroy=function(){r.off('click',l),g()},u}var r=angular.element(t.document.body),s=Element.prototype.matchesSelector||Element.prototype.webkitMatchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector;return i}]}).directive('bsDropdown',['$window','$sce','$dropdown',function(e,t,n){return{restrict:'EAC',scope:!0,link:function(e,t,a,o){var i={scope:e};angular.forEach(['placement','container','delay','trigger','keyboard','html','animation','template','id'],function(e){angular.isDefined(a[e])&&(i[e]=a[e])});var r=/^(false|0|)$/i;angular.forEach(['html','container'],function(e){angular.isDefined(a[e])&&r.test(a[e])&&(i[e]=!1)}),a.bsDropdown&&e.$watch(a.bsDropdown,function(t,n){e.content=t},!0),a.bsShow&&e.$watch(a.bsShow,function(e,t){s&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(dropdown),?/i)),e===!0?s.show():s.hide())});var s=n(t,i);e.$on('$destroy',function(){s&&s.destroy(),i=null,s=null})}}}]),angular.module('mgcrea.ngStrap.helpers.dateFormatter',[]).service('$dateFormatter',['$locale','dateFilter',function(e,t){function n(e){return/(h+)([:\.])?(m+)([:\.])?(s*)[ ]?(a?)/i.exec(e).slice(1)}this.getDefaultLocale=function(){return e.id},this.getDatetimeFormat=function(t,n){return e.DATETIME_FORMATS[t]||t},this.weekdaysShort=function(t){return e.DATETIME_FORMATS.SHORTDAY},this.hoursFormat=function(e){return n(e)[0]},this.minutesFormat=function(e){return n(e)[2]},this.secondsFormat=function(e){return n(e)[4]},this.timeSeparator=function(e){return n(e)[1]},this.showSeconds=function(e){return!!n(e)[4]},this.showAM=function(e){return!!n(e)[5]},this.formatDate=function(e,n,a,o){return t(e,n,o)}}]),angular.module('mgcrea.ngStrap.helpers.dateParser',[]).provider('$dateParser',['$localeProvider',function(e){function t(){this.year=1970,this.month=0,this.day=1,this.hours=0,this.minutes=0,this.seconds=0,this.milliseconds=0}function n(){}function a(e){return!isNaN(parseFloat(e))&&isFinite(e)}function o(e,t){for(var n=e.length,a=t.toString().toLowerCase(),o=0;n>o;o++)if(e[o].toLowerCase()===a)return o;return-1}t.prototype.setMilliseconds=function(e){this.milliseconds=e},t.prototype.setSeconds=function(e){this.seconds=e},t.prototype.setMinutes=function(e){this.minutes=e},t.prototype.setHours=function(e){this.hours=e},t.prototype.getHours=function(){return this.hours},t.prototype.setDate=function(e){this.day=e},t.prototype.setMonth=function(e){this.month=e},t.prototype.setFullYear=function(e){this.year=e},t.prototype.fromDate=function(e){return this.year=e.getFullYear(),this.month=e.getMonth(),this.day=e.getDate(),this.hours=e.getHours(),this.minutes=e.getMinutes(),this.seconds=e.getSeconds(),this.milliseconds=e.getMilliseconds(),this},t.prototype.toDate=function(){return new Date(this.year,this.month,this.day,this.hours,this.minutes,this.seconds,this.milliseconds)};var i=t.prototype,r=this.defaults={format:'shortDate',strict:!1};this.$get=['$locale','dateFilter',function(e,s){var l=function(l){function u(e){var t,n=Object.keys(h),a=[],o=[],i=e;for(t=0;t<n.length;t++)if(e.split(n[t]).length>1){var r=i.search(n[t]);e=e.split(n[t]).join(''),h[n[t]]&&(a[r]=h[n[t]])}return angular.forEach(a,function(e){e&&o.push(e)}),o}function c(e){return e.replace(/\//g,'[\\/]').replace('/-/g','[-]').replace(/\./g,'[.]').replace(/\\s/g,'[\\s]')}function d(e){var t,n=Object.keys($),a=e;for(t=0;t<n.length;t++)a=a.split(n[t]).join('${'+t+'}');for(t=0;t<n.length;t++)a=a.split('${'+t+'}').join('('+$[n[t]]+')');return e=c(e),new RegExp('^'+a+'$',['i'])}var f,p,g=angular.extend({},r,l),m={},$={sss:'[0-9]{3}',ss:'[0-5][0-9]',s:g.strict?'[1-5]?[0-9]':'[0-9]|[0-5][0-9]',mm:'[0-5][0-9]',m:g.strict?'[1-5]?[0-9]':'[0-9]|[0-5][0-9]',HH:'[01][0-9]|2[0-3]',H:g.strict?'1?[0-9]|2[0-3]':'[01]?[0-9]|2[0-3]',hh:'[0][1-9]|[1][012]',h:g.strict?'[1-9]|1[012]':'0?[1-9]|1[012]',a:'AM|PM',EEEE:e.DATETIME_FORMATS.DAY.join('|'),EEE:e.DATETIME_FORMATS.SHORTDAY.join('|'),dd:'0[1-9]|[12][0-9]|3[01]',d:g.strict?'[1-9]|[1-2][0-9]|3[01]':'0?[1-9]|[1-2][0-9]|3[01]',MMMM:e.DATETIME_FORMATS.MONTH.join('|'),MMM:e.DATETIME_FORMATS.SHORTMONTH.join('|'),MM:'0[1-9]|1[012]',M:g.strict?'[1-9]|1[012]':'0?[1-9]|1[012]',yyyy:'[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',yy:'[0-9]{2}',y:g.strict?'-?(0|[1-9][0-9]{0,3})':'-?0*[0-9]{1,4}'},h={sss:i.setMilliseconds,ss:i.setSeconds,s:i.setSeconds,mm:i.setMinutes,m:i.setMinutes,HH:i.setHours,H:i.setHours,hh:i.setHours,h:i.setHours,EEEE:n,EEE:n,dd:i.setDate,d:i.setDate,a:function(e){var t=this.getHours()%12;return this.setHours(e.match(/pm/i)?t+12:t)},MMMM:function(t){return this.setMonth(o(e.DATETIME_FORMATS.MONTH,t))},MMM:function(t){return this.setMonth(o(e.DATETIME_FORMATS.SHORTMONTH,t))},MM:function(e){return this.setMonth(1*e-1)},M:function(e){return this.setMonth(1*e-1)},yyyy:i.setFullYear,yy:function(e){return this.setFullYear(2e3+1*e)},y:i.setFullYear};return m.init=function(){m.$format=e.DATETIME_FORMATS[g.format]||g.format,f=d(m.$format),p=u(m.$format)},m.isValid=function(e){return angular.isDate(e)?!isNaN(e.getTime()):f.test(e)},m.parse=function(n,a,o,i){o&&(o=e.DATETIME_FORMATS[o]||o),angular.isDate(n)&&(n=s(n,o||m.$format,i));var r=o?d(o):f,l=o?u(o):p,c=r.exec(n);if(!c)return!1;for(var g=(new t).fromDate(a&&!isNaN(a.getTime())?a:new Date(1970,0,1,0)),$=0;$<c.length-1;$++)l[$]&&l[$].call(g,c[$+1]);var h=g.toDate();return parseInt(g.day,10)!==h.getDate()?!1:h},m.getDateForAttribute=function(e,t){var n;if('today'===t){var o=new Date;n=new Date(o.getFullYear(),o.getMonth(),o.getDate()+('maxDate'===e?1:0),0,0,0,'minDate'===e?0:-1)}else n=angular.isString(t)&&t.match(/^".+"$/)?new Date(t.substr(1,t.length-2)):a(t)?new Date(parseInt(t,10)):angular.isString(t)&&0===t.length?'minDate'===e?-(1/0):+(1/0):new Date(t);return n},m.getTimeForAttribute=function(e,t){var n;return n='now'===t?(new Date).setFullYear(1970,0,1):angular.isString(t)&&t.match(/^".+"$/)?new Date(t.substr(1,t.length-2)).setFullYear(1970,0,1):a(t)?new Date(parseInt(t,10)).setFullYear(1970,0,1):angular.isString(t)&&0===t.length?'minTime'===e?-(1/0):+(1/0):m.parse(t,new Date(1970,0,1,0))},m.daylightSavingAdjust=function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},m.timezoneOffsetAdjust=function(e,t,n){return e?(t&&'UTC'===t&&(e=new Date(e.getTime()),e.setMinutes(e.getMinutes()+(n?-1:1)*e.getTimezoneOffset())),e):null},m.init(),m};return l}]}]),angular.module('mgcrea.ngStrap.helpers.debounce',[]).factory('debounce',['$timeout',function(e){return function(t,n,a){var o=null;return function(){var i=this,r=arguments,s=a&&!o;return o&&e.cancel(o),o=e(function(){o=null,a||t.apply(i,r)},n,!1),s&&t.apply(i,r),o}}}]).factory('throttle',['$timeout',function(e){return function(t,n,a){var o=null;return a||(a={}),function(){var i=this,r=arguments;o||(a.leading!==!1&&t.apply(i,r),o=e(function(){o=null,a.trailing!==!1&&t.apply(i,r)},n,!1))}}}]),angular.module('mgcrea.ngStrap.helpers.dimensions',[]).factory('dimensions',['$document','$window',function(t,n){var a=(angular.element,{}),o=a.nodeName=function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()};a.css=function(t,n,a){var o;return o=t.currentStyle?t.currentStyle[n]:e.getComputedStyle?e.getComputedStyle(t)[n]:t.style[n],a===!0?parseFloat(o)||0:o},a.offset=function(t){var n=t.getBoundingClientRect(),a=t.ownerDocument;return{width:n.width||t.offsetWidth,height:n.height||t.offsetHeight,top:n.top+(e.pageYOffset||a.documentElement.scrollTop)-(a.documentElement.clientTop||0),left:n.left+(e.pageXOffset||a.documentElement.scrollLeft)-(a.documentElement.clientLeft||0)}},a.setOffset=function(e,t,n){var o,i,r,s,l,u,c,d=a.css(e,'position'),f=angular.element(e),p={};'static'===d&&(e.style.position='relative'),l=a.offset(e),r=a.css(e,'top'),u=a.css(e,'left'),c=('absolute'===d||'fixed'===d)&&(r+u).indexOf('auto')>-1,c?(o=a.position(e),s=o.top,i=o.left):(s=parseFloat(r)||0,i=parseFloat(u)||0),angular.isFunction(t)&&(t=t.call(e,n,l)),
9
- null!==t.top&&(p.top=t.top-l.top+s),null!==t.left&&(p.left=t.left-l.left+i),'using'in t?t.using.call(f,p):f.css({top:p.top+'px',left:p.left+'px'})},a.position=function(e){var t,n,r={top:0,left:0};return'fixed'===a.css(e,'position')?n=e.getBoundingClientRect():(t=i(e),n=a.offset(e),o(t,'html')||(r=a.offset(t)),r.top+=a.css(t,'borderTopWidth',!0),r.left+=a.css(t,'borderLeftWidth',!0)),{width:e.offsetWidth,height:e.offsetHeight,top:n.top-r.top-a.css(e,'marginTop',!0),left:n.left-r.left-a.css(e,'marginLeft',!0)}};var i=function(e){var t=e.ownerDocument,n=e.offsetParent||t;if(o(n,'#document'))return t.documentElement;for(;n&&!o(n,'html')&&'static'===a.css(n,'position');)n=n.offsetParent;return n||t.documentElement};return a.height=function(e,t){var n=e.offsetHeight;return t?n+=a.css(e,'marginTop',!0)+a.css(e,'marginBottom',!0):n-=a.css(e,'paddingTop',!0)+a.css(e,'paddingBottom',!0)+a.css(e,'borderTopWidth',!0)+a.css(e,'borderBottomWidth',!0),n},a.width=function(e,t){var n=e.offsetWidth;return t?n+=a.css(e,'marginLeft',!0)+a.css(e,'marginRight',!0):n-=a.css(e,'paddingLeft',!0)+a.css(e,'paddingRight',!0)+a.css(e,'borderLeftWidth',!0)+a.css(e,'borderRightWidth',!0),n},a}]),angular.module('mgcrea.ngStrap.helpers.parseOptions',[]).provider('$parseOptions',function(){var e=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+(.*?))?$/};this.$get=['$parse','$q',function(t,n){function a(a,o){function i(e,t){return e.map(function(e,n){var a,o,i={};return i[c]=e,a=u(t,i),o=p(t,i),{label:a,value:o,index:n}})}var r={},s=angular.extend({},e,o);r.$values=[];var l,u,c,d,f,p,g;return r.init=function(){r.$match=l=a.match(s.regexp),u=t(l[2]||l[1]),c=l[4]||l[6],d=l[5],f=t(l[3]||''),p=t(l[2]?l[1]:c),g=t(l[7])},r.valuesFn=function(e,t){return n.when(g(e,t)).then(function(t){return r.$values=t?i(t,e):{},r.$values})},r.displayValue=function(e){var t={};return t[c]=e,u(t)},r.init(),r}return a}]}),angular.version.minor<3&&angular.version.dot<14&&angular.module('ng').factory('$$rAF',['$window','$timeout',function(e,t){var n=e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame,a=e.cancelAnimationFrame||e.webkitCancelAnimationFrame||e.mozCancelAnimationFrame||e.webkitCancelRequestAnimationFrame,o=!!n,i=o?function(e){var t=n(e);return function(){a(t)}}:function(e){var n=t(e,16.66,!1);return function(){t.cancel(n)}};return i.supported=o,i}]),angular.module('mgcrea.ngStrap.modal',['mgcrea.ngStrap.helpers.dimensions']).provider('$modal',function(){var e=this.defaults={animation:'am-fade',backdropAnimation:'am-fade',prefixClass:'modal',prefixEvent:'modal',placement:'top',template:'modal/modal.tpl.html',contentTemplate:!1,container:!1,element:null,backdrop:!0,keyboard:!0,html:!1,show:!0};this.$get=['$window','$rootScope','$compile','$q','$templateCache','$http','$animate','$timeout','$sce','dimensions',function(n,a,o,i,r,s,l,u,c,d){function f(t){function n(){f.$emit(d.prefixEvent+'.show',u)}function i(){f.$emit(d.prefixEvent+'.hide',u),w.removeClass(d.prefixClass+'-open'),d.animation&&w.removeClass(d.prefixClass+'-with-'+d.animation)}function r(e){e.target===e.currentTarget&&('static'===d.backdrop?u.focus():u.hide())}function s(e){e.preventDefault()}var u={},d=u.$options=angular.extend({},e,t);u.$promise=m(d.template);var f=u.$scope=d.scope&&d.scope.$new()||a.$new();d.element||d.container||(d.container='body'),u.$id=d.id||d.element&&d.element.attr('id')||'',$(['title','content'],function(e){d[e]&&(f[e]=c.trustAsHtml(d[e]))}),f.$hide=function(){f.$$postDigest(function(){u.hide()})},f.$show=function(){f.$$postDigest(function(){u.show()})},f.$toggle=function(){f.$$postDigest(function(){u.toggle()})},u.$isShown=f.$isShown=!1,d.contentTemplate&&(u.$promise=u.$promise.then(function(e){var n=angular.element(e);return m(d.contentTemplate).then(function(e){var a=g('[ng-bind="content"]',n[0]).removeAttr('ng-bind').html(e);return t.template||a.next().remove(),n[0].outerHTML})}));var b,D,k=angular.element('<div class="'+d.prefixClass+'-backdrop"/>');return k.css({position:'fixed',top:'0px',left:'0px',bottom:'0px',right:'0px','z-index':1038}),u.$promise.then(function(e){angular.isObject(e)&&(e=e.data),d.html&&(e=e.replace(y,'ng-bind-html="')),e=h.apply(e),b=o(e),u.init()}),u.init=function(){d.show&&f.$$postDigest(function(){u.show()})},u.destroy=function(){D&&(D.remove(),D=null),k&&(k.remove(),k=null),f.$destroy()},u.show=function(){if(!u.$isShown){var e,t;if(angular.isElement(d.container)?(e=d.container,t=d.container[0].lastChild?angular.element(d.container[0].lastChild):null):d.container?(e=g(d.container),t=e[0]&&e[0].lastChild?angular.element(e[0].lastChild):null):(e=null,t=d.element),D=u.$element=b(f,function(e,t){}),!f.$emit(d.prefixEvent+'.show.before',u).defaultPrevented){D.css({display:'block'}).addClass(d.placement),d.animation&&(d.backdrop&&k.addClass(d.backdropAnimation),D.addClass(d.animation)),d.backdrop&&l.enter(k,w,null);var a=l.enter(D,e,t,n);a&&a.then&&a.then(n),u.$isShown=f.$isShown=!0,p(f);var o=D[0];v(function(){o.focus()}),w.addClass(d.prefixClass+'-open'),d.animation&&w.addClass(d.prefixClass+'-with-'+d.animation),d.backdrop&&(D.on('click',r),k.on('click',r),k.on('wheel',s)),d.keyboard&&D.on('keyup',u.$onKeyUp)}}},u.hide=function(){if(u.$isShown&&!f.$emit(d.prefixEvent+'.hide.before',u).defaultPrevented){var e=l.leave(D,i);e&&e.then&&e.then(i),d.backdrop&&l.leave(k),u.$isShown=f.$isShown=!1,p(f),d.backdrop&&(D.off('click',r),k.off('click',r),k.off('wheel',s)),d.keyboard&&D.off('keyup',u.$onKeyUp)}},u.toggle=function(){u.$isShown?u.hide():u.show()},u.focus=function(){D[0].focus()},u.$onKeyUp=function(e){27===e.which&&u.$isShown&&(u.hide(),e.stopPropagation())},u}function p(e){e.$$phase||e.$root&&e.$root.$$phase||e.$digest()}function g(e,n){return angular.element((n||t).querySelectorAll(e))}function m(e){return b[e]?b[e]:b[e]=s.get(e,{cache:r}).then(function(e){return e.data})}var $=angular.forEach,h=String.prototype.trim,v=n.requestAnimationFrame||n.setTimeout,w=angular.element(n.document.body),y=/ng-bind="/gi,b={};return f}]}).directive('bsModal',['$window','$sce','$modal',function(e,t,n){return{restrict:'EAC',scope:!0,link:function(e,a,o,i){var r={scope:e,element:a,show:!1};angular.forEach(['template','contentTemplate','placement','backdrop','keyboard','html','container','animation','id','prefixEvent','prefixClass'],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var s=/^(false|0|)$/i;angular.forEach(['backdrop','keyboard','html','container'],function(e){angular.isDefined(o[e])&&s.test(o[e])&&(r[e]=!1)}),angular.forEach(['title','content'],function(n){o[n]&&o.$observe(n,function(a,o){e[n]=t.trustAsHtml(a)})}),o.bsModal&&e.$watch(o.bsModal,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var l=n(r);a.on(o.trigger||'click',l.toggle),e.$on('$destroy',function(){l&&l.destroy(),r=null,l=null})}}}]),angular.module('mgcrea.ngStrap.navbar',[]).provider('$navbar',function(){var e=this.defaults={activeClass:'active',routeAttr:'data-match-route',strict:!1};this.$get=function(){return{defaults:e}}}).directive('bsNavbar',['$window','$location','$navbar',function(e,t,n){var a=n.defaults;return{restrict:'A',link:function(e,n,o,i){var r=angular.copy(a);angular.forEach(Object.keys(a),function(e){angular.isDefined(o[e])&&(r[e]=o[e])}),e.$watch(function(){return t.path()},function(e,t){var a=n[0].querySelectorAll('li['+r.routeAttr+']');angular.forEach(a,function(t){var n=angular.element(t),a=n.attr(r.routeAttr).replace('/','\\/');r.strict&&(a='^'+a+'$');var o=new RegExp(a,'i');o.test(e)?n.addClass(r.activeClass):n.removeClass(r.activeClass)})})}}}]),angular.module('mgcrea.ngStrap.popover',['mgcrea.ngStrap.tooltip']).provider('$popover',function(){var e=this.defaults={animation:'am-fade',customClass:'',container:!1,target:!1,placement:'right',template:'popover/popover.tpl.html',contentTemplate:!1,trigger:'click',keyboard:!0,html:!1,title:'',content:'',delay:0,autoClose:!1};this.$get=['$tooltip',function(t){function n(n,a){var o=angular.extend({},e,a),i=t(n,o);return o.content&&(i.$scope.content=o.content),i}return n}]}).directive('bsPopover',['$window','$sce','$popover',function(e,t,n){var a=e.requestAnimationFrame||e.setTimeout;return{restrict:'EAC',scope:!0,link:function(e,o,i){var r={scope:e};angular.forEach(['template','contentTemplate','placement','container','delay','trigger','html','animation','customClass','autoClose','id','prefixClass','prefixEvent'],function(e){angular.isDefined(i[e])&&(r[e]=i[e])});var s=/^(false|0|)$/i;angular.forEach(['html','container','autoClose'],function(e){angular.isDefined(i[e])&&s.test(i[e])&&(r[e]=!1)});var l=o.attr('data-target');angular.isDefined(l)&&(r.target=s.test(l)?!1:l),angular.forEach(['title','content'],function(n){i[n]&&i.$observe(n,function(o,i){e[n]=t.trustAsHtml(o),angular.isDefined(i)&&a(function(){u&&u.$applyPlacement()})})}),i.bsPopover&&e.$watch(i.bsPopover,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t,angular.isDefined(n)&&a(function(){u&&u.$applyPlacement()})},!0),i.bsShow&&e.$watch(i.bsShow,function(e,t){u&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(popover),?/i)),e===!0?u.show():u.hide())}),i.viewport&&e.$watch(i.viewport,function(e){u&&angular.isDefined(e)&&u.setViewport(e)});var u=n(o,r);e.$on('$destroy',function(){u&&u.destroy(),r=null,u=null})}}}]),angular.module('mgcrea.ngStrap.scrollspy',['mgcrea.ngStrap.helpers.debounce','mgcrea.ngStrap.helpers.dimensions']).provider('$scrollspy',function(){var e=this.$$spies={},n=this.defaults={debounce:150,throttle:100,offset:100};this.$get=['$window','$document','$rootScope','dimensions','debounce','throttle',function(a,o,i,r,s,l){function u(e,t){return e[0].nodeName&&e[0].nodeName.toLowerCase()===t.toLowerCase()}function c(o){var c=angular.extend({},n,o);c.element||(c.element=p);var g=u(c.element,'body'),m=g?d:c.element,$=g?'window':c.id;if(e[$])return e[$].$$count++,e[$];var h,v,w,y,b,D,k,S,x={},T=x.$trackedElements=[],C=[];return x.init=function(){this.$$count=1,y=s(this.checkPosition,c.debounce),b=l(this.checkPosition,c.throttle),m.on('click',this.checkPositionWithEventLoop),d.on('resize',y),m.on('scroll',b),D=s(this.checkOffsets,c.debounce),h=i.$on('$viewContentLoaded',D),v=i.$on('$includeContentLoaded',D),D(),$&&(e[$]=x)},x.destroy=function(){this.$$count--,this.$$count>0||(m.off('click',this.checkPositionWithEventLoop),d.off('resize',y),m.off('scroll',b),h(),v(),$&&delete e[$])},x.checkPosition=function(){if(C.length){if(S=(g?a.pageYOffset:m.prop('scrollTop'))||0,k=Math.max(a.innerHeight,f.prop('clientHeight')),S<C[0].offsetTop&&w!==C[0].target)return x.$activateElement(C[0]);for(var e=C.length;e--;)if(!angular.isUndefined(C[e].offsetTop)&&null!==C[e].offsetTop&&w!==C[e].target&&!(S<C[e].offsetTop||C[e+1]&&S>C[e+1].offsetTop))return x.$activateElement(C[e])}},x.checkPositionWithEventLoop=function(){setTimeout(x.checkPosition,1)},x.$activateElement=function(e){if(w){var t=x.$getTrackedElement(w);t&&(t.source.removeClass('active'),u(t.source,'li')&&u(t.source.parent().parent(),'li')&&t.source.parent().parent().removeClass('active'))}w=e.target,e.source.addClass('active'),u(e.source,'li')&&u(e.source.parent().parent(),'li')&&e.source.parent().parent().addClass('active')},x.$getTrackedElement=function(e){return T.filter(function(t){return t.target===e})[0]},x.checkOffsets=function(){angular.forEach(T,function(e){var n=t.querySelector(e.target);e.offsetTop=n?r.offset(n).top:null,c.offset&&null!==e.offsetTop&&(e.offsetTop-=1*c.offset)}),C=T.filter(function(e){return null!==e.offsetTop}).sort(function(e,t){return e.offsetTop-t.offsetTop}),y()},x.trackElement=function(e,t){T.push({target:e,source:t})},x.untrackElement=function(e,t){for(var n,a=T.length;a--;)if(T[a].target===e&&T[a].source===t){n=a;break}T=T.splice(n,1)},x.activate=function(e){T[e].addClass('active')},x.init(),x}var d=angular.element(a),f=angular.element(o.prop('documentElement')),p=angular.element(a.document.body);return c}]}).directive('bsScrollspy',['$rootScope','debounce','dimensions','$scrollspy',function(e,t,n,a){return{restrict:'EAC',link:function(e,t,n){var o={scope:e};angular.forEach(['offset','target'],function(e){angular.isDefined(n[e])&&(o[e]=n[e])});var i=a(o);i.trackElement(o.target,t),e.$on('$destroy',function(){i&&(i.untrackElement(o.target,t),i.destroy()),o=null,i=null})}}}]).directive('bsScrollspyList',['$rootScope','debounce','dimensions','$scrollspy',function(e,t,n,a){return{restrict:'A',compile:function(e,t){var n=e[0].querySelectorAll('li > a[href]');angular.forEach(n,function(e){var t=angular.element(e);t.parent().attr('bs-scrollspy','').attr('data-target',t.attr('href'))})}}}]),angular.module('mgcrea.ngStrap.select',['mgcrea.ngStrap.tooltip','mgcrea.ngStrap.helpers.parseOptions']).provider('$select',function(){var e=this.defaults={animation:'am-fade',prefixClass:'select',prefixEvent:'$select',placement:'bottom-left',template:'select/select.tpl.html',trigger:'focus',container:!1,keyboard:!0,html:!1,delay:0,multiple:!1,allNoneButtons:!1,sort:!0,caretHtml:'&nbsp;<span class="caret"></span>',placeholder:'Choose among the following...',allText:'All',noneText:'None',maxLength:3,maxLengthHtml:'selected',iconCheckmark:'glyphicon glyphicon-ok'};this.$get=['$window','$document','$rootScope','$tooltip','$timeout',function(t,n,a,o,i){function r(t,n,a){var r={},s=angular.extend({},e,a);r=o(t,s);var u=r.$scope;u.$matches=[],u.$activeIndex=s.multiple?[]:-1,u.$isMultiple=s.multiple,u.$showAllNoneButtons=s.allNoneButtons&&s.multiple,u.$iconCheckmark=s.iconCheckmark,u.$allText=s.allText,u.$noneText=s.noneText,u.$activate=function(e){u.$$postDigest(function(){r.activate(e)})},u.$select=function(e,t){u.$$postDigest(function(){r.select(e)})},u.$isVisible=function(){return r.$isVisible()},u.$isActive=function(e){return r.$isActive(e)},u.$selectAll=function(){for(var e=0;e<u.$matches.length;e++)u.$isActive(e)||u.$select(e)},u.$selectNone=function(){for(var e=0;e<u.$matches.length;e++)u.$isActive(e)&&u.$select(e)},r.update=function(e){u.$matches=e,r.$updateActiveIndex()},r.activate=function(e){return s.multiple?(r.$isActive(e)?u.$activeIndex.splice(u.$activeIndex.indexOf(e),1):u.$activeIndex.push(e),s.sort&&u.$activeIndex.sort()):u.$activeIndex=e,u.$activeIndex},r.select=function(e){var t=u.$matches[e].value;u.$apply(function(){r.activate(e),s.multiple?n.$setViewValue(u.$activeIndex.map(function(e){return u.$matches[e].value})):(n.$setViewValue(t),r.hide())}),u.$emit(s.prefixEvent+'.select',t,e,r)},r.$updateActiveIndex=function(){n.$modelValue&&u.$matches.length?u.$activeIndex=s.multiple&&angular.isArray(n.$modelValue)?n.$modelValue.map(function(e){return r.$getIndex(e)}):r.$getIndex(n.$modelValue):u.$activeIndex>=u.$matches.length&&(u.$activeIndex=s.multiple?[]:0)},r.$isVisible=function(){return s.minLength&&n?u.$matches.length&&n.$viewValue.length>=s.minLength:u.$matches.length},r.$isActive=function(e){return s.multiple?-1!==u.$activeIndex.indexOf(e):u.$activeIndex===e},r.$getIndex=function(e){var t=u.$matches.length,n=t;if(t){for(n=t;n--&&u.$matches[n].value!==e;);if(!(0>n))return n}},r.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),l){var t=angular.element(e.target);t.triggerHandler('click')}},r.$onKeyDown=function(e){return/(9|13|38|40)/.test(e.keyCode)?(e.preventDefault(),e.stopPropagation(),s.multiple&&9===e.keyCode?r.hide():s.multiple||13!==e.keyCode&&9!==e.keyCode?void(s.multiple||(38===e.keyCode&&u.$activeIndex>0?u.$activeIndex--:38===e.keyCode&&u.$activeIndex<0?u.$activeIndex=u.$matches.length-1:40===e.keyCode&&u.$activeIndex<u.$matches.length-1?u.$activeIndex++:angular.isUndefined(u.$activeIndex)&&(u.$activeIndex=0),u.$digest())):r.select(u.$activeIndex)):void 0};var c=r.show;r.show=function(){c(),s.multiple&&r.$element.addClass('select-multiple'),i(function(){r.$element.on(l?'touchstart':'mousedown',r.$onMouseDown),s.keyboard&&t.on('keydown',r.$onKeyDown)},0,!1)};var d=r.hide;return r.hide=function(){s.multiple||n.$modelValue||(u.$activeIndex=-1),r.$element.off(l?'touchstart':'mousedown',r.$onMouseDown),s.keyboard&&t.off('keydown',r.$onKeyDown),d(!0)},r}var s=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),l='createTouch'in t.document&&s;return r.defaults=e,r}]}).directive('bsSelect',['$window','$parse','$q','$select','$parseOptions',function(e,t,n,a,o){var i=a.defaults;return{restrict:'EAC',require:'ngModel',link:function(e,t,n,r){var s={scope:e,placeholder:i.placeholder};angular.forEach(['placement','container','delay','trigger','keyboard','html','animation','template','placeholder','allNoneButtons','maxLength','maxLengthHtml','allText','noneText','iconCheckmark','autoClose','id','sort','caretHtml','prefixClass','prefixEvent'],function(e){angular.isDefined(n[e])&&(s[e]=n[e])});var l=/^(false|0|)$/i;angular.forEach(['html','container','allNoneButtons','sort'],function(e){angular.isDefined(n[e])&&l.test(n[e])&&(s[e]=!1)});var u=t.attr('data-multiple');if(angular.isDefined(u)&&(s.multiple=l.test(u)?!1:u),'select'===t[0].nodeName.toLowerCase()){var c=t;c.css('display','none'),t=angular.element('<button type="button" class="btn btn-default"></button>'),c.after(t)}var d=o(n.bsOptions),f=a(t,r,s),p=d.$match[7].replace(/\|.+/,'').trim();e.$watchCollection(p,function(t,n){d.valuesFn(e,r).then(function(e){f.update(e),r.$render()})}),e.$watch(n.ngModel,function(e,t){f.$updateActiveIndex(),r.$render()},!0),r.$render=function(){var e,n;s.multiple&&angular.isArray(r.$modelValue)?(e=r.$modelValue.map(function(e){return n=f.$getIndex(e),angular.isDefined(n)?f.$scope.$matches[n].label:!1}).filter(angular.isDefined),e=e.length>(s.maxLength||i.maxLength)?e.length+' '+(s.maxLengthHtml||i.maxLengthHtml):e.join(', ')):(n=f.$getIndex(r.$modelValue),e=angular.isDefined(n)?f.$scope.$matches[n].label:!1),t.html((e?e:s.placeholder)+(s.caretHtml?s.caretHtml:i.caretHtml))},s.multiple&&(r.$isEmpty=function(e){return!e||0===e.length}),e.$on('$destroy',function(){f&&f.destroy(),s=null,f=null})}}}]),angular.module('mgcrea.ngStrap.tab',[]).provider('$tab',function(){var e=this.defaults={animation:'am-fade',template:'tab/tab.tpl.html',navClass:'nav-tabs',activeClass:'active'},t=this.controller=function(t,n,a){var o=this;o.$options=angular.copy(e),angular.forEach(['animation','navClass','activeClass'],function(e){angular.isDefined(a[e])&&(o.$options[e]=a[e])}),t.$navClass=o.$options.navClass,t.$activeClass=o.$options.activeClass,o.$panes=t.$panes=[],o.$activePaneChangeListeners=o.$viewChangeListeners=[],o.$push=function(e){angular.isUndefined(o.$panes.$active)&&t.$setActive(e.name||0),o.$panes.push(e)},o.$remove=function(e){var t,n=o.$panes.indexOf(e),a=o.$panes.$active;t=angular.isString(a)?o.$panes.map(function(e){return e.name}).indexOf(a):o.$panes.$active,o.$panes.splice(n,1),t>n?t--:n===t&&t===o.$panes.length&&t--,t>=0&&t<o.$panes.length?o.$setActive(o.$panes[t].name||t):o.$setActive()},o.$setActive=t.$setActive=function(e){o.$panes.$active=e,o.$activePaneChangeListeners.forEach(function(e){e()})},o.$isActive=t.$isActive=function(e,t){return o.$panes.$active===e.name||o.$panes.$active===t}};this.$get=function(){var n={};return n.defaults=e,n.controller=t,n}}).directive('bsTabs',['$window','$animate','$tab','$parse',function(e,t,n,a){var o=n.defaults;return{require:['?ngModel','bsTabs'],transclude:!0,scope:!0,controller:['$scope','$element','$attrs',n.controller],templateUrl:function(e,t){return t.template||o.template},link:function(e,t,n,o){var i=o[0],r=o[1];if(i&&(r.$activePaneChangeListeners.push(function(){i.$setViewValue(r.$panes.$active)}),i.$formatters.push(function(e){return r.$setActive(e),e})),n.bsActivePane){var s=a(n.bsActivePane);r.$activePaneChangeListeners.push(function(){s.assign(e,r.$panes.$active)}),e.$watch(n.bsActivePane,function(e,t){r.$setActive(e)},!0)}}}}]).directive('bsPane',['$window','$animate','$sce',function(e,t,n){return{require:['^?ngModel','^bsTabs'],scope:!0,link:function(e,a,o,i){function r(){var n=s.$panes.indexOf(e);t[s.$isActive(e,n)?'addClass':'removeClass'](a,s.$options.activeClass)}var s=(i[0],i[1]);a.addClass('tab-pane'),o.$observe('title',function(t,a){e.title=n.trustAsHtml(t)}),e.name=o.name,s.$options.animation&&a.addClass(s.$options.animation),o.$observe('disabled',function(t,n){e.disabled=e.$eval(t)}),s.$push(e),e.$on('$destroy',function(){s.$remove(e)}),s.$activePaneChangeListeners.push(function(){r()}),r()}}}]),angular.module('mgcrea.ngStrap.timepicker',['mgcrea.ngStrap.helpers.dateParser','mgcrea.ngStrap.helpers.dateFormatter','mgcrea.ngStrap.tooltip']).provider('$timepicker',function(){var e=this.defaults={animation:'am-fade',prefixClass:'timepicker',placement:'bottom-left',template:'timepicker/timepicker.tpl.html',trigger:'focus',container:!1,keyboard:!0,html:!1,delay:0,useNative:!0,timeType:'date',timeFormat:'shortTime',timezone:null,modelTimeFormat:null,autoclose:!1,minTime:-(1/0),maxTime:+(1/0),length:5,hourStep:1,minuteStep:5,secondStep:5,roundDisplay:!1,iconUp:'glyphicon glyphicon-chevron-up',iconDown:'glyphicon glyphicon-chevron-down',arrowBehavior:'pager'};this.$get=['$window','$document','$rootScope','$sce','$dateFormatter','$tooltip','$timeout',function(t,n,a,o,i,r,s){function l(t,n,a){function o(e){var t=6e4*g.minuteStep;return new Date(Math.floor(e.getTime()/t)*t)}function l(e,n){var a=e+n;if(t[0].createTextRange){var o=t[0].createTextRange();o.collapse(!0),o.moveStart('character',e),o.moveEnd('character',a),o.select()}else t[0].setSelectionRange?t[0].setSelectionRange(e,a):angular.isUndefined(t[0].selectionStart)&&(t[0].selectionStart=e,t[0].selectionEnd=a)}function d(){t[0].focus()}var f=r(t,angular.extend({},e,a)),p=a.scope,g=f.$options,m=f.$scope,$=g.lang,h=function(e,t,n){return i.formatDate(e,t,$,n)},v=0,w=g.roundDisplay?o(new Date):new Date,y=n.$dateValue||w,b={hour:y.getHours(),meridian:y.getHours()<12,minute:y.getMinutes(),second:y.getSeconds(),millisecond:y.getMilliseconds()},D=i.getDatetimeFormat(g.timeFormat,$),k=i.hoursFormat(D),S=i.timeSeparator(D),x=i.minutesFormat(D),T=i.secondsFormat(D),C=i.showSeconds(D),M=i.showAM(D);m.$iconUp=g.iconUp,m.$iconDown=g.iconDown,m.$select=function(e,t){f.select(e,t)},m.$moveIndex=function(e,t){f.$moveIndex(e,t)},m.$switchMeridian=function(e){f.switchMeridian(e)},f.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())?(f.$date=e,angular.extend(b,{hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}),f.$build()):f.$isBuilt||f.$build()},f.select=function(e,t,a){(!n.$dateValue||isNaN(n.$dateValue.getTime()))&&(n.$dateValue=new Date(1970,0,1)),angular.isDate(e)||(e=new Date(e)),0===t?n.$dateValue.setHours(e.getHours()):1===t?n.$dateValue.setMinutes(e.getMinutes()):2===t&&n.$dateValue.setSeconds(e.getSeconds()),n.$setViewValue(angular.copy(n.$dateValue)),n.$render(),g.autoclose&&!a&&s(function(){f.hide(!0)})},f.switchMeridian=function(e){if(n.$dateValue&&!isNaN(n.$dateValue.getTime())){var t=(e||n.$dateValue).getHours();n.$dateValue.setHours(12>t?t+12:t-12),n.$setViewValue(angular.copy(n.$dateValue)),n.$render()}},f.$build=function(){var e,t,n=m.midIndex=parseInt(g.length/2,10),a=[];for(e=0;e<g.length;e++)t=new Date(1970,0,1,b.hour-(n-e)*g.hourStep),a.push({date:t,label:h(t,k),selected:f.$date&&f.$isSelected(t,0),disabled:f.$isDisabled(t,0)});var o,i=[];for(e=0;e<g.length;e++)o=new Date(1970,0,1,0,b.minute-(n-e)*g.minuteStep),i.push({date:o,label:h(o,x),selected:f.$date&&f.$isSelected(o,1),disabled:f.$isDisabled(o,1)});var r,s=[];for(e=0;e<g.length;e++)r=new Date(1970,0,1,0,0,b.second-(n-e)*g.secondStep),s.push({date:r,label:h(r,T),selected:f.$date&&f.$isSelected(r,2),disabled:f.$isDisabled(r,2)});var l=[];for(e=0;e<g.length;e++)l.push(C?[a[e],i[e],s[e]]:[a[e],i[e]]);m.rows=l,m.showSeconds=C,m.showAM=M,m.isAM=(f.$date||a[n].date).getHours()<12,m.timeSeparator=S,f.$isBuilt=!0},f.$isSelected=function(e,t){return f.$date?0===t?e.getHours()===f.$date.getHours():1===t?e.getMinutes()===f.$date.getMinutes():2===t?e.getSeconds()===f.$date.getSeconds():void 0:!1},f.$isDisabled=function(e,t){var n;return 0===t?n=e.getTime()+6e4*b.minute+1e3*b.second:1===t?n=e.getTime()+36e5*b.hour+1e3*b.second:2===t&&(n=e.getTime()+36e5*b.hour+6e4*b.minute),n<1*g.minTime||n>1*g.maxTime},m.$arrowAction=function(e,t){'picker'===g.arrowBehavior?f.$setTimeByStep(e,t):f.$moveIndex(e,t)},f.$setTimeByStep=function(e,t){{var n=new Date(f.$date),a=n.getHours(),o=(h(n,k).length,n.getMinutes()),i=(h(n,x).length,n.getSeconds());h(n,T).length}0===t?n.setHours(a-parseInt(g.hourStep,10)*e):1===t?n.setMinutes(o-parseInt(g.minuteStep,10)*e):2===t&&n.setSeconds(i-parseInt(g.secondStep,10)*e),f.select(n,t,!0)},f.$moveIndex=function(e,t){var n;0===t?(n=new Date(1970,0,1,b.hour+e*g.length,b.minute,b.second),angular.extend(b,{hour:n.getHours()})):1===t?(n=new Date(1970,0,1,b.hour,b.minute+e*g.length*g.minuteStep,b.second),angular.extend(b,{minute:n.getMinutes()})):2===t&&(n=new Date(1970,0,1,b.hour,b.minute,b.second+e*g.length*g.secondStep),angular.extend(b,{second:n.getSeconds()})),f.$build()},f.$onMouseDown=function(e){if('input'!==e.target.nodeName.toLowerCase()&&e.preventDefault(),e.stopPropagation(),c){var t=angular.element(e.target);'button'!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler('click')}},f.$onKeyDown=function(e){if(/(38|37|39|40|13)/.test(e.keyCode)&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),e.stopPropagation(),13===e.keyCode)return f.hide(!0);var t=new Date(f.$date),n=t.getHours(),a=h(t,k).length,o=t.getMinutes(),i=h(t,x).length,r=t.getSeconds(),s=h(t,T).length,u=1,c=/(37|39)/.test(e.keyCode),d=2+1*C+1*M;c&&(37===e.keyCode?v=1>v?d-1:v-1:39===e.keyCode&&(v=d-1>v?v+1:0));var m=[0,a],$=0;38===e.keyCode&&($=-1),40===e.keyCode&&($=1);var w=2===v&&C,y=2===v&&!C||3===v&&C;0===v?(t.setHours(n+$*parseInt(g.hourStep,10)),a=h(t,k).length,m=[0,a]):1===v?(t.setMinutes(o+$*parseInt(g.minuteStep,10)),i=h(t,x).length,m=[a+u,i]):w?(t.setSeconds(r+$*parseInt(g.secondStep,10)),s=h(t,T).length,m=[a+u+i+u,s]):y&&(c||f.switchMeridian(),m=[a+u+i+u+(s+u)*C,2]),f.select(t,v,!0),l(m[0],m[1]),p.$digest()}};var E=f.init;f.init=function(){return u&&g.useNative?(t.prop('type','time'),void t.css('-webkit-appearance','textfield')):(c&&(t.prop('type','text'),t.attr('readonly','true'),t.on('click',d)),void E())};var A=f.destroy;f.destroy=function(){u&&g.useNative&&t.off('click',d),A()};var F=f.show;f.show=function(){F(),s(function(){f.$element.on(c?'touchstart':'mousedown',f.$onMouseDown),g.keyboard&&t.on('keydown',f.$onKeyDown)},0,!1)};var V=f.hide;return f.hide=function(e){f.$isShown&&(f.$element.off(c?'touchstart':'mousedown',f.$onMouseDown),g.keyboard&&t.off('keydown',f.$onKeyDown),V(e))},f}var u=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),c='createTouch'in t.document&&u;return e.lang||(e.lang=i.getDefaultLocale()),l.defaults=e,l}]}).directive('bsTimepicker',['$window','$parse','$q','$dateFormatter','$dateParser','$timepicker',function(e,t,n,a,o,i){{var r=i.defaults,s=/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent);e.requestAnimationFrame||e.setTimeout}return{restrict:'EAC',require:'ngModel',link:function(e,t,n,l){function u(e){if(angular.isDate(e)){var t=isNaN(d.minTime)||new Date(e.getTime()).setFullYear(1970,0,1)>=d.minTime,n=isNaN(d.maxTime)||new Date(e.getTime()).setFullYear(1970,0,1)<=d.maxTime,a=t&&n;l.$setValidity('date',a),l.$setValidity('min',t),l.$setValidity('max',n),a&&(l.$dateValue=e)}}function c(){return!l.$dateValue||isNaN(l.$dateValue.getTime())?'':m(l.$dateValue,d.timeFormat)}var d={scope:e,controller:l};angular.forEach(['placement','container','delay','trigger','keyboard','html','animation','template','autoclose','timeType','timeFormat','timezone','modelTimeFormat','useNative','hourStep','minuteStep','secondStep','length','arrowBehavior','iconUp','iconDown','roundDisplay','id','prefixClass','prefixEvent'],function(e){angular.isDefined(n[e])&&(d[e]=n[e])});var f=/^(false|0|)$/i;angular.forEach(['html','container','autoclose','useNative','roundDisplay'],function(e){angular.isDefined(n[e])&&f.test(n[e])&&(d[e]=!1)}),n.bsShow&&e.$watch(n.bsShow,function(e,t){p&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(timepicker),?/i)),e===!0?p.show():p.hide())}),s&&(d.useNative||r.useNative)&&(d.timeFormat='HH:mm');var p=i(t,l,d);d=p.$options;var g=d.lang,m=function(e,t,n){return a.formatDate(e,t,g,n)},$=o({format:d.timeFormat,lang:g});angular.forEach(['minTime','maxTime'],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){p.$options[e]=$.getTimeForAttribute(e,t),!isNaN(p.$options[e])&&p.$build(),u(l.$dateValue)})}),e.$watch(n.ngModel,function(e,t){p.update(l.$dateValue)},!0),l.$parsers.unshift(function(e){var t;if(!e)return l.$setValidity('date',!0),null;var n=angular.isDate(e)?e:$.parse(e,l.$dateValue);return!n||isNaN(n.getTime())?void l.$setValidity('date',!1):(u(n),'string'===d.timeType?(t=$.timezoneOffsetAdjust(n,d.timezone,!0),m(t,d.modelTimeFormat||d.timeFormat)):(t=$.timezoneOffsetAdjust(l.$dateValue,d.timezone,!0),'number'===d.timeType?t.getTime():'unix'===d.timeType?t.getTime()/1e3:'iso'===d.timeType?t.toISOString():new Date(t)))}),l.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:'string'===d.timeType?$.parse(e,null,d.modelTimeFormat):new Date('unix'===d.timeType?1e3*e:e),l.$dateValue=$.timezoneOffsetAdjust(t,d.timezone),c()}),l.$render=function(){t.val(c())},e.$on('$destroy',function(){p&&p.destroy(),d=null,p=null})}}}]),angular.module('mgcrea.ngStrap.tooltip',['mgcrea.ngStrap.helpers.dimensions']).provider('$tooltip',function(){var e=this.defaults={animation:'am-fade',customClass:'',prefixClass:'tooltip',prefixEvent:'tooltip',container:!1,target:!1,placement:'top',template:'tooltip/tooltip.tpl.html',contentTemplate:!1,trigger:'hover focus',keyboard:!1,html:!1,show:!1,title:'',type:'',delay:0,autoClose:!1,bsEnabled:!0,viewport:{selector:'body',padding:0}};this.$get=['$window','$rootScope','$compile','$q','$templateCache','$http','$animate','$sce','dimensions','$$rAF','$timeout',function(n,a,o,i,r,s,l,u,c,d,f){function p(i,r){function s(){N.$emit(H.prefixEvent+'.show',I)}function p(){if(N.$emit(H.prefixEvent+'.hide',I),z===B){if(W&&'focus'===H.trigger)return i[0].blur();O()}}function b(){var e=H.trigger.split(' ');angular.forEach(e,function(e){'click'===e?i.on('click',I.toggle):'manual'!==e&&(i.on('hover'===e?'mouseenter':'focus',I.enter),i.on('hover'===e?'mouseleave':'blur',I.leave),'button'===P&&'hover'!==e&&i.on(v?'touchstart':'mousedown',I.$onFocusElementMouseDown))})}function D(){for(var e=H.trigger.split(' '),t=e.length;t--;){var n=e[t];'click'===n?i.off('click',I.toggle):'manual'!==n&&(i.off('hover'===n?'mouseenter':'focus',I.enter),i.off('hover'===n?'mouseleave':'blur',I.leave),'button'===P&&'hover'!==n&&i.off(v?'touchstart':'mousedown',I.$onFocusElementMouseDown))}}function k(){'focus'!==H.trigger?z.on('keyup',I.$onKeyUp):i.on('keyup',I.$onFocusKeyUp)}function S(){'focus'!==H.trigger?z.off('keyup',I.$onKeyUp):i.off('keyup',I.$onFocusKeyUp)}function x(){f(function(){z.on('click',C),y.on('click',I.hide),_=!0},0,!1)}function T(){_&&(z.off('click',C),y.off('click',I.hide),_=!1)}function C(e){e.stopPropagation()}function M(e){e=e||H.target||i;var a=e[0],o='BODY'===a.tagName,r=a.getBoundingClientRect(),s={};for(var l in r)s[l]=r[l];null===s.width&&(s=angular.extend({},s,{width:r.right-r.left,height:r.bottom-r.top}));var u=o?{top:0,left:0}:c.offset(a),d={scroll:o?t.documentElement.scrollTop||t.body.scrollTop:e.prop('scrollTop')||0},f=o?{width:t.documentElement.clientWidth,height:n.innerHeight}:null;return angular.extend({},s,d,f,u)}function E(e,t,n,a){var o,i=e.split('-');switch(i[0]){case'right':o={top:t.top+t.height/2-a/2,left:t.left+t.width};break;case'bottom':o={top:t.top+t.height,left:t.left+t.width/2-n/2};break;case'left':
10
- o={top:t.top+t.height/2-a/2,left:t.left-n};break;default:o={top:t.top-a,left:t.left+t.width/2-n/2}}if(!i[1])return o;if('top'===i[0]||'bottom'===i[0])switch(i[1]){case'left':o.left=t.left;break;case'right':o.left=t.left+t.width-n}else if('left'===i[0]||'right'===i[0])switch(i[1]){case'top':o.top=t.top-a;break;case'bottom':o.top=t.top+t.height}return o}function A(e,t){var n=z[0],a=n.offsetWidth,o=n.offsetHeight,i=parseInt(c.css(n,'margin-top'),10),r=parseInt(c.css(n,'margin-left'),10);isNaN(i)&&(i=0),isNaN(r)&&(r=0),e.top=e.top+i,e.left=e.left+r,c.setOffset(n,angular.extend({using:function(e){z.css({top:Math.round(e.top)+'px',left:Math.round(e.left)+'px',right:''})}},e),0);var s=n.offsetWidth,l=n.offsetHeight;if('top'===t&&l!==o&&(e.top=e.top+o-l),!/top-left|top-right|bottom-left|bottom-right/.test(t)){var u=F(t,e,s,l);if(u.left?e.left+=u.left:e.top+=u.top,c.setOffset(n,e),/top|right|bottom|left/.test(t)){var d=/top|bottom/.test(t),f=d?2*u.left-a+s:2*u.top-o+l,p=d?'offsetWidth':'offsetHeight';V(f,n[p],d)}}}function F(e,t,n,a){var o={top:0,left:0},i=H.viewport&&m(H.viewport.selector||H.viewport);if(!i)return o;var r=H.viewport&&H.viewport.padding||0,s=M(i);if(/right|left/.test(e)){var l=t.top-r-s.scroll,u=t.top+r-s.scroll+a;l<s.top?o.top=s.top-l:u>s.top+s.height&&(o.top=s.top+s.height-u)}else{var c=t.left-r,d=t.left+r+n;c<s.left?o.left=s.left-c:d>s.width&&(o.left=s.left+s.width-d)}return o}function V(e,t,n){var a=m('.tooltip-arrow, .arrow',z[0]);a.css(n?'left':'top',50*(1-e/t)+'%').css(n?'top':'left','')}function O(){clearTimeout(R),I.$isShown&&null!==z&&(H.autoClose&&T(),H.keyboard&&S()),j&&(j.$destroy(),j=null),z&&(z.remove(),z=I.$element=null)}var I={},P=i[0].nodeName.toLowerCase(),H=I.$options=angular.extend({},e,r);I.$promise=$(H.template);var N=I.$scope=H.scope&&H.scope.$new()||a.$new();if(H.delay&&angular.isString(H.delay)){var L=H.delay.split(',').map(parseFloat);H.delay=L.length>1?{show:L[0],hide:L[1]}:L[0]}I.$id=H.id||i.attr('id')||'',H.title&&(N.title=u.trustAsHtml(H.title)),N.$setEnabled=function(e){N.$$postDigest(function(){I.setEnabled(e)})},N.$hide=function(){N.$$postDigest(function(){I.hide()})},N.$show=function(){N.$$postDigest(function(){I.show()})},N.$toggle=function(){N.$$postDigest(function(){I.toggle()})},I.$isShown=N.$isShown=!1;var R,Y;H.contentTemplate&&(I.$promise=I.$promise.then(function(e){var t=angular.element(e);return $(H.contentTemplate).then(function(e){var n=m('[ng-bind="content"]',t[0]);return n.length||(n=m('[ng-bind="title"]',t[0])),n.removeAttr('ng-bind').html(e),t[0].outerHTML})}));var q,z,K,U,j;I.$promise.then(function(e){angular.isObject(e)&&(e=e.data),H.html&&(e=e.replace(w,'ng-bind-html="')),e=h.apply(e),K=e,q=o(e),I.init()}),I.init=function(){H.delay&&angular.isNumber(H.delay)&&(H.delay={show:H.delay,hide:H.delay}),'self'===H.container?U=i:angular.isElement(H.container)?U=H.container:H.container&&(U=m(H.container)),b(),H.target&&(H.target=angular.isElement(H.target)?H.target:m(H.target)),H.show&&N.$$postDigest(function(){'focus'===H.trigger?i[0].focus():I.show()})},I.destroy=function(){D(),O(),N.$destroy()},I.enter=function(){return clearTimeout(R),Y='in',H.delay&&H.delay.show?void(R=setTimeout(function(){'in'===Y&&I.show()},H.delay.show)):I.show()},I.show=function(){if(H.bsEnabled&&!I.$isShown){N.$emit(H.prefixEvent+'.show.before',I);var e,t;H.container?(e=U,t=U[0].lastChild?angular.element(U[0].lastChild):null):(e=null,t=i),z&&O(),j=I.$scope.$new(),z=I.$element=q(j,function(e,t){}),z.css({top:'-9999px',left:'-9999px',right:'auto',display:'block',visibility:'hidden'}),H.animation&&z.addClass(H.animation),H.type&&z.addClass(H.prefixClass+'-'+H.type),H.customClass&&z.addClass(H.customClass),t?t.after(z):e.prepend(z),I.$isShown=N.$isShown=!0,g(N),I.$applyPlacement();var n=l.enter(z,e,t,s);n&&n.then&&n.then(s),g(N),d(function(){z&&z.css({visibility:'visible'})}),H.keyboard&&('focus'!==H.trigger&&I.focus(),k()),H.autoClose&&x()}},I.leave=function(){return clearTimeout(R),Y='out',H.delay&&H.delay.hide?void(R=setTimeout(function(){'out'===Y&&I.hide()},H.delay.hide)):I.hide()};var W,B;I.hide=function(e){if(I.$isShown){N.$emit(H.prefixEvent+'.hide.before',I),W=e,B=z;var t=l.leave(z,p);t&&t.then&&t.then(p),I.$isShown=N.$isShown=!1,g(N),H.keyboard&&null!==z&&S(),H.autoClose&&null!==z&&T()}},I.toggle=function(){I.$isShown?I.leave():I.enter()},I.focus=function(){z[0].focus()},I.setEnabled=function(e){H.bsEnabled=e},I.setViewport=function(e){H.viewport=e},I.$applyPlacement=function(){if(z){var t=H.placement,n=/\s?auto?\s?/i,a=n.test(t);a&&(t=t.replace(n,'')||e.placement),z.addClass(H.placement);var o=M(),r=z.prop('offsetWidth'),s=z.prop('offsetHeight');if(a){var l=t,u=H.container?m(H.container):i.parent(),c=M(u);l.indexOf('bottom')>=0&&o.bottom+s>c.bottom?t=l.replace('bottom','top'):l.indexOf('top')>=0&&o.top-s<c.top&&(t=l.replace('top','bottom')),('right'===l||'bottom-left'===l||'top-left'===l)&&o.right+r>c.width?t='right'===l?'left':t.replace('left','right'):('left'===l||'bottom-right'===l||'top-right'===l)&&o.left-r<c.left&&(t='left'===l?'right':t.replace('right','left')),z.removeClass(l).addClass(t)}var d=E(t,o,r,s);A(d,t)}},I.$onKeyUp=function(e){27===e.which&&I.$isShown&&(I.hide(),e.stopPropagation())},I.$onFocusKeyUp=function(e){27===e.which&&(i[0].blur(),e.stopPropagation())},I.$onFocusElementMouseDown=function(e){e.preventDefault(),e.stopPropagation(),I.$isShown?i[0].blur():i[0].focus()};var _=!1;return I}function g(e){e.$$phase||e.$root&&e.$root.$$phase||e.$digest()}function m(e,n){return angular.element((n||t).querySelectorAll(e))}function $(e){return b[e]?b[e]:b[e]=s.get(e,{cache:r}).then(function(e){return e.data})}var h=String.prototype.trim,v='createTouch'in n.document,w=/ng-bind="/gi,y=angular.element(n.document),b={};return p}]}).directive('bsTooltip',['$window','$location','$sce','$tooltip','$$rAF',function(e,t,n,a,o){return{restrict:'EAC',scope:!0,link:function(e,t,i,r){var s={scope:e};angular.forEach(['template','contentTemplate','placement','container','delay','trigger','html','animation','backdropAnimation','type','customClass','id'],function(e){angular.isDefined(i[e])&&(s[e]=i[e])});var l=/^(false|0|)$/i;angular.forEach(['html','container'],function(e){angular.isDefined(i[e])&&l.test(i[e])&&(s[e]=!1)});var u=t.attr('data-target');angular.isDefined(u)&&(s.target=l.test(u)?!1:u),e.hasOwnProperty('title')||(e.title=''),i.$observe('title',function(t){if(angular.isDefined(t)||!e.hasOwnProperty('title')){var a=e.title;e.title=n.trustAsHtml(t),angular.isDefined(a)&&o(function(){c&&c.$applyPlacement()})}}),i.bsTooltip&&e.$watch(i.bsTooltip,function(t,n){angular.isObject(t)?angular.extend(e,t):e.title=t,angular.isDefined(n)&&o(function(){c&&c.$applyPlacement()})},!0),i.bsShow&&e.$watch(i.bsShow,function(e,t){c&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(tooltip),?/i)),e===!0?c.show():c.hide())}),i.bsEnabled&&e.$watch(i.bsEnabled,function(e,t){c&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|1|,?(tooltip),?/i)),c.setEnabled(e===!1?!1:!0))}),i.viewport&&e.$watch(i.viewport,function(e){c&&angular.isDefined(e)&&c.setViewport(e)});var c=a(t,s);e.$on('$destroy',function(){c&&c.destroy(),s=null,c=null})}}}]),angular.module('mgcrea.ngStrap.typeahead',['mgcrea.ngStrap.tooltip','mgcrea.ngStrap.helpers.parseOptions']).provider('$typeahead',function(){var e=this.defaults={animation:'am-fade',prefixClass:'typeahead',prefixEvent:'$typeahead',placement:'bottom-left',template:'typeahead/typeahead.tpl.html',trigger:'focus',container:!1,keyboard:!0,html:!1,delay:0,minLength:1,filter:'filter',limit:6,autoSelect:!1,comparator:'',trimValue:!0};this.$get=['$window','$rootScope','$tooltip','$timeout',function(t,n,a,o){function i(t,n,i){var r={},s=angular.extend({},e,i);r=a(t,s);var l=i.scope,u=r.$scope;u.$resetMatches=function(){u.$matches=[],u.$activeIndex=s.autoSelect?0:-1},u.$resetMatches(),u.$activate=function(e){u.$$postDigest(function(){r.activate(e)})},u.$select=function(e,t){u.$$postDigest(function(){r.select(e)})},u.$isVisible=function(){return r.$isVisible()},r.update=function(e){u.$matches=e,u.$activeIndex>=e.length&&(u.$activeIndex=s.autoSelect?0:-1),/^(bottom|bottom-left|bottom-right)$/.test(s.placement)||o(r.$applyPlacement)},r.activate=function(e){u.$activeIndex=e},r.select=function(e){if(-1!==e){var t=u.$matches[e].value;n.$setViewValue(t),n.$render(),u.$resetMatches(),l&&l.$digest(),u.$emit(s.prefixEvent+'.select',t,e,r)}},r.$isVisible=function(){return s.minLength&&n?u.$matches.length&&angular.isString(n.$viewValue)&&n.$viewValue.length>=s.minLength:!!u.$matches.length},r.$getIndex=function(e){var t=u.$matches.length,n=t;if(t){for(n=t;n--&&u.$matches[n].value!==e;);if(!(0>n))return n}},r.$onMouseDown=function(e){e.preventDefault(),e.stopPropagation()},r.$onKeyDown=function(e){/(38|40|13)/.test(e.keyCode)&&(!r.$isVisible()||13===e.keyCode&&-1===u.$activeIndex||(e.preventDefault(),e.stopPropagation()),13===e.keyCode&&u.$matches.length?r.select(u.$activeIndex):38===e.keyCode&&u.$activeIndex>0?u.$activeIndex--:40===e.keyCode&&u.$activeIndex<u.$matches.length-1?u.$activeIndex++:angular.isUndefined(u.$activeIndex)&&(u.$activeIndex=0),u.$digest())};var c=r.show;r.show=function(){c(),o(function(){r.$element.on('mousedown',r.$onMouseDown),s.keyboard&&t.on('keydown',r.$onKeyDown)},0,!1)};var d=r.hide;return r.hide=function(){r.$element.off('mousedown',r.$onMouseDown),s.keyboard&&t.off('keydown',r.$onKeyDown),s.autoSelect||r.activate(-1),d()},r}angular.element(t.document.body);return i.defaults=e,i}]}).directive('bsTypeahead',['$window','$parse','$q','$typeahead','$parseOptions',function(e,t,a,o,i){var r=o.defaults;return{restrict:'EAC',require:'ngModel',link:function(e,t,a,s){var l={scope:e};angular.forEach(['placement','container','delay','trigger','keyboard','html','animation','template','filter','limit','minLength','watchOptions','selectMode','autoSelect','comparator','id','prefixEvent','prefixClass'],function(e){angular.isDefined(a[e])&&(l[e]=a[e])});var u=/^(false|0|)$/i;angular.forEach(['html','container','trimValue'],function(e){angular.isDefined(a[e])&&u.test(a[e])&&(l[e]=!1)}),t.attr('autocomplete','off');var c=l.filter||r.filter,d=l.limit||r.limit,f=l.comparator||r.comparator,p=a.bsOptions;c&&(p+=' | '+c+':$viewValue'),f&&(p+=':'+f),d&&(p+=' | limitTo:'+d);var g=i(p),m=o(t,s,l);if(l.watchOptions){var $=g.$match[7].replace(/\|.+/,'').replace(/\(.*\)/g,'').trim();e.$watchCollection($,function(t,n){g.valuesFn(e,s).then(function(e){m.update(e),s.$render()})})}e.$watch(a.ngModel,function(t,n){e.$modelValue=t,g.valuesFn(e,s).then(function(e){if(l.selectMode&&!e.length&&t.length>0)return void s.$setViewValue(s.$viewValue.substring(0,s.$viewValue.length-1));e.length>d&&(e=e.slice(0,d));var n=m.$isVisible();n&&m.update(e),(1!==e.length||e[0].value!==t)&&(!n&&m.update(e),s.$render())})}),s.$formatters.push(function(e){var t=g.displayValue(e);return t===n?'':t}),s.$render=function(){if(s.$isEmpty(s.$viewValue))return t.val('');var e=m.$getIndex(s.$modelValue),n=angular.isDefined(e)?m.$scope.$matches[e].label:s.$viewValue;n=angular.isObject(n)?g.displayValue(n):n;var a=n?n.toString().replace(/<(?:.|\n)*?>/gm,''):'';t.val(l.trimValue===!1?a:a.trim())},e.$on('$destroy',function(){m&&m.destroy(),l=null,m=null})}}}])}(window,document);
8
+ !function(e,t,n){'use strict';angular.module('mgcrea.ngStrap',['mgcrea.ngStrap.modal','mgcrea.ngStrap.aside','mgcrea.ngStrap.alert','mgcrea.ngStrap.button','mgcrea.ngStrap.select','mgcrea.ngStrap.datepicker','mgcrea.ngStrap.timepicker','mgcrea.ngStrap.navbar','mgcrea.ngStrap.tooltip','mgcrea.ngStrap.popover','mgcrea.ngStrap.dropdown','mgcrea.ngStrap.typeahead','mgcrea.ngStrap.scrollspy','mgcrea.ngStrap.affix','mgcrea.ngStrap.tab','mgcrea.ngStrap.collapse']),angular.module('mgcrea.ngStrap.affix',['mgcrea.ngStrap.helpers.dimensions','mgcrea.ngStrap.helpers.debounce']).provider('$affix',function(){var e=this.defaults={offsetTop:'auto',inlineStyles:!0};this.$get=['$window','debounce','dimensions',function(t,n,a){function o(o,s){function l(e,t,n){var a=u(),o=c();return v>=a?'top':null!==e&&a+e<=t.top?'middle':null!==w&&t.top+n+$>=o-w?'bottom':'middle'}function u(){return p[0]===t?t.pageYOffset:p[0].scrollTop}function c(){return p[0]===t?t.document.body.scrollHeight:p[0].scrollHeight}var d={},f=angular.extend({},e,s),p=f.target,g='affix affix-top affix-bottom',m=!1,$=0,h=0,v=0,w=0,y=null,b=null,D=o.parent();if(f.offsetParent)if(f.offsetParent.match(/^\d+$/))for(var k=0;k<1*f.offsetParent-1;k++)D=D.parent();else D=angular.element(f.offsetParent);return d.init=function(){this.$parseOffsets(),h=a.offset(o[0]).top+$,m=!o[0].style.width,p.on('scroll',this.checkPosition),p.on('click',this.checkPositionWithEventLoop),r.on('resize',this.$debouncedOnResize),this.checkPosition(),this.checkPositionWithEventLoop()},d.destroy=function(){p.off('scroll',this.checkPosition),p.off('click',this.checkPositionWithEventLoop),r.off('resize',this.$debouncedOnResize)},d.checkPositionWithEventLoop=function(){setTimeout(d.checkPosition,1)},d.checkPosition=function(){var e=u(),t=a.offset(o[0]),n=a.height(o[0]),r=l(b,t,n);y!==r&&(y=r,o.removeClass(g).addClass('affix'+('middle'!==r?'-'+r:'')),'top'===r?(b=null,m&&o.css('width',''),f.inlineStyles&&(o.css('position',f.offsetParent?'':'relative'),o.css('top',''))):'bottom'===r?(b=f.offsetUnpin?-(1*f.offsetUnpin):t.top-e,m&&o.css('width',''),f.inlineStyles&&(o.css('position',f.offsetParent?'':'relative'),o.css('top',f.offsetParent?'':i[0].offsetHeight-w-n-h+'px'))):(b=null,m&&o.css('width',o[0].offsetWidth+'px'),f.inlineStyles&&(o.css('position','fixed'),o.css('top',$+'px'))))},d.$onResize=function(){d.$parseOffsets(),d.checkPosition()},d.$debouncedOnResize=n(d.$onResize,50),d.$parseOffsets=function(){var e=o.css('position');f.inlineStyles&&o.css('position',f.offsetParent?'':'relative'),f.offsetTop&&('auto'===f.offsetTop&&(f.offsetTop='+0'),f.offsetTop.match(/^[-+]\d+$/)?($=1*-f.offsetTop,v=f.offsetParent?a.offset(D[0]).top+1*f.offsetTop:a.offset(o[0]).top-a.css(o[0],'marginTop',!0)+1*f.offsetTop):v=1*f.offsetTop),f.offsetBottom&&(w=f.offsetParent&&f.offsetBottom.match(/^[-+]\d+$/)?c()-(a.offset(D[0]).top+a.height(D[0]))+1*f.offsetBottom+1:1*f.offsetBottom),f.inlineStyles&&o.css('position',e)},d.init(),d}var i=angular.element(t.document.body),r=angular.element(t);return o}]}).directive('bsAffix',['$affix','$window',function(e,t){return{restrict:'EAC',require:'^?bsAffixTarget',link:function(n,a,o,i){var r={scope:n,target:i?i.$element:angular.element(t)};angular.forEach(['offsetTop','offsetBottom','offsetParent','offsetUnpin','inlineStyles'],function(e){if(angular.isDefined(o[e])){var t=o[e];/true/i.test(t)&&(t=!0),/false/i.test(t)&&(t=!1),r[e]=t}});var s=e(a,r);n.$on('$destroy',function(){s&&s.destroy(),r=null,s=null})}}}]).directive('bsAffixTarget',function(){return{controller:['$element',function(e){this.$element=e}]}}),angular.module('mgcrea.ngStrap.alert',['mgcrea.ngStrap.modal']).provider('$alert',function(){var e=this.defaults={animation:'am-fade',prefixClass:'alert',prefixEvent:'alert',placement:null,template:'alert/alert.tpl.html',container:!1,element:null,backdrop:!1,keyboard:!0,show:!0,duration:!1,type:!1,dismissable:!0};this.$get=['$modal','$timeout',function(t,n){function a(a){var o={},i=angular.extend({},e,a);o=t(i),o.$scope.dismissable=!!i.dismissable,i.type&&(o.$scope.type=i.type);var r=o.show;return i.duration&&(o.show=function(){r(),n(function(){o.hide()},1e3*i.duration)}),o}return a}]}).directive('bsAlert',['$window','$sce','$alert',function(e,t,n){e.requestAnimationFrame||e.setTimeout;return{restrict:'EAC',scope:!0,link:function(e,a,o,i){var r={scope:e,element:a,show:!1};angular.forEach(['template','placement','keyboard','html','container','animation','duration','dismissable'],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var s=/^(false|0|)$/i;angular.forEach(['keyboard','html','container','dismissable'],function(e){angular.isDefined(o[e])&&s.test(o[e])&&(r[e]=!1)}),e.hasOwnProperty('title')||(e.title=''),angular.forEach(['title','content','type'],function(n){o[n]&&o.$observe(n,function(a,o){e[n]=t.trustAsHtml(a)})}),o.bsAlert&&e.$watch(o.bsAlert,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var l=n(r);a.on(o.trigger||'click',l.toggle),e.$on('$destroy',function(){l&&l.destroy(),r=null,l=null})}}}]),angular.module('mgcrea.ngStrap.aside',['mgcrea.ngStrap.modal']).provider('$aside',function(){var e=this.defaults={animation:'am-fade-and-slide-right',prefixClass:'aside',prefixEvent:'aside',placement:'right',template:'aside/aside.tpl.html',contentTemplate:!1,container:!1,element:null,backdrop:!0,keyboard:!0,html:!1,show:!0};this.$get=['$modal',function(t){function n(n){var a={},o=angular.extend({},e,n);return a=t(o)}return n}]}).directive('bsAside',['$window','$sce','$aside',function(e,t,n){e.requestAnimationFrame||e.setTimeout;return{restrict:'EAC',scope:!0,link:function(e,a,o,i){var r={scope:e,element:a,show:!1};angular.forEach(['template','contentTemplate','placement','backdrop','keyboard','html','container','animation'],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var s=/^(false|0|)$/i;angular.forEach(['backdrop','keyboard','html','container'],function(e){angular.isDefined(o[e])&&s.test(o[e])&&(r[e]=!1)}),angular.forEach(['title','content'],function(n){o[n]&&o.$observe(n,function(a,o){e[n]=t.trustAsHtml(a)})}),o.bsAside&&e.$watch(o.bsAside,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var l=n(r);a.on(o.trigger||'click',l.toggle),e.$on('$destroy',function(){l&&l.destroy(),r=null,l=null})}}}]),angular.module('mgcrea.ngStrap.collapse',[]).provider('$collapse',function(){var e=this.defaults={animation:'am-collapse',disallowToggle:!1,activeClass:'in',startCollapsed:!1,allowMultiple:!1},t=this.controller=function(t,n,a){function o(e){for(var t=l.$targets.$active,n=0;n<t.length;n++)e<t[n]&&(t[n]=t[n]-1),t[n]===l.$targets.length&&(t[n]=l.$targets.length-1)}function i(e){var t=l.$targets.$active;return-1===t.indexOf(e)?!1:!0}function r(e){var t=l.$targets.$active.indexOf(e);-1!==t&&l.$targets.$active.splice(t,1)}function s(e){l.$options.allowMultiple||l.$targets.$active.splice(0,1),-1===l.$targets.$active.indexOf(e)&&l.$targets.$active.push(e)}var l=this;l.$options=angular.copy(e),angular.forEach(['animation','disallowToggle','activeClass','startCollapsed','allowMultiple'],function(e){angular.isDefined(a[e])&&(l.$options[e]=a[e])});var u=/^(false|0|)$/i;angular.forEach(['disallowToggle','startCollapsed','allowMultiple'],function(e){angular.isDefined(a[e])&&u.test(a[e])&&(l.$options[e]=!1)}),l.$toggles=[],l.$targets=[],l.$viewChangeListeners=[],l.$registerToggle=function(e){l.$toggles.push(e)},l.$registerTarget=function(e){l.$targets.push(e)},l.$unregisterToggle=function(e){var t=l.$toggles.indexOf(e);l.$toggles.splice(t,1)},l.$unregisterTarget=function(e){var t=l.$targets.indexOf(e);l.$targets.splice(t,1),l.$options.allowMultiple&&r(e),o(t),l.$viewChangeListeners.forEach(function(e){e()})},l.$targets.$active=l.$options.startCollapsed?[]:[0],l.$setActive=t.$setActive=function(e){angular.isArray(e)?l.$targets.$active=e:l.$options.disallowToggle?s(e):i(e)?r(e):s(e),l.$viewChangeListeners.forEach(function(e){e()})},l.$activeIndexes=function(){return l.$options.allowMultiple?l.$targets.$active:1===l.$targets.$active.length?l.$targets.$active[0]:-1}};this.$get=function(){var n={};return n.defaults=e,n.controller=t,n}}).directive('bsCollapse',['$window','$animate','$collapse',function(e,t,n){n.defaults;return{require:['?ngModel','bsCollapse'],controller:['$scope','$element','$attrs',n.controller],link:function(e,t,n,a){var o=a[0],i=a[1];o&&(i.$viewChangeListeners.push(function(){o.$setViewValue(i.$activeIndexes())}),o.$formatters.push(function(e){if(angular.isArray(e))i.$setActive(e);else{var t=i.$activeIndexes();angular.isArray(t)?-1===t.indexOf(1*e)&&i.$setActive(1*e):t!==1*e&&i.$setActive(1*e)}return e}))}}}]).directive('bsCollapseToggle',function(){return{require:['^?ngModel','^bsCollapse'],link:function(e,t,n,a){var o=(a[0],a[1]);t.attr('data-toggle','collapse'),o.$registerToggle(t),e.$on('$destroy',function(){o.$unregisterToggle(t)}),t.on('click',function(){var a=n.bsCollapseToggle||o.$toggles.indexOf(t);o.$setActive(1*a),e.$apply()})}}}).directive('bsCollapseTarget',['$animate',function(e){return{require:['^?ngModel','^bsCollapse'],link:function(t,n,a,o){function i(){var t=r.$targets.indexOf(n),a=r.$activeIndexes(),o='removeClass';angular.isArray(a)?-1!==a.indexOf(t)&&(o='addClass'):t===a&&(o='addClass'),e[o](n,r.$options.activeClass)}var r=(o[0],o[1]);n.addClass('collapse'),r.$options.animation&&n.addClass(r.$options.animation),r.$registerTarget(n),t.$on('$destroy',function(){r.$unregisterTarget(n)}),r.$viewChangeListeners.push(function(){i()}),i()}}}]),angular.module('mgcrea.ngStrap.datepicker',['mgcrea.ngStrap.helpers.dateParser','mgcrea.ngStrap.helpers.dateFormatter','mgcrea.ngStrap.tooltip']).provider('$datepicker',function(){var e=this.defaults={animation:'am-fade',prefixClass:'datepicker',placement:'bottom-left',template:'datepicker/datepicker.tpl.html',trigger:'focus',container:!1,keyboard:!0,html:!1,delay:0,useNative:!1,dateType:'date',dateFormat:'shortDate',timezone:null,modelDateFormat:null,dayFormat:'dd',monthFormat:'MMM',yearFormat:'yyyy',monthTitleFormat:'MMMM yyyy',yearTitleFormat:'yyyy',strictFormat:!1,autoclose:!1,minDate:-(1/0),maxDate:+(1/0),startView:0,minView:0,startWeek:0,daysOfWeekDisabled:'',iconLeft:'glyphicon glyphicon-chevron-left',iconRight:'glyphicon glyphicon-chevron-right'};this.$get=['$window','$document','$rootScope','$sce','$dateFormatter','datepickerViews','$tooltip','$timeout',function(t,n,a,o,i,r,s,l){function u(t,n,a){function o(e){e.selected=u.$isSelected(e.date)}function i(){t[0].focus()}var u=s(t,angular.extend({},e,a)),f=a.scope,p=u.$options,g=u.$scope;p.startView&&(p.startView-=p.minView);var m=r(u);u.$views=m.views;var $=m.viewDate;g.$mode=p.startView,g.$iconLeft=p.iconLeft,g.$iconRight=p.iconRight;var h=u.$views[g.$mode];g.$select=function(e){u.select(e)},g.$selectPane=function(e){u.$selectPane(e)},g.$toggleMode=function(){u.setMode((g.$mode+1)%u.$views.length)},u.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())&&(u.$date=e,h.update.call(h,e)),u.$build(!0)},u.updateDisabledDates=function(e){p.disabledDateRanges=e;for(var t=0,n=g.rows.length;n>t;t++)angular.forEach(g.rows[t],u.$setDisabledEl)},u.select=function(e,t){angular.isDate(n.$dateValue)||(n.$dateValue=new Date(e)),!g.$mode||t?(n.$setViewValue(angular.copy(e)),n.$render(),p.autoclose&&!t&&l(function(){u.hide(!0)})):(angular.extend($,{year:e.getFullYear(),month:e.getMonth(),date:e.getDate()}),u.setMode(g.$mode-1),u.$build())},u.setMode=function(e){g.$mode=e,h=u.$views[g.$mode],u.$build()},u.$build=function(e){e===!0&&h.built||(e!==!1||h.built)&&h.build.call(h)},u.$updateSelected=function(){for(var e=0,t=g.rows.length;t>e;e++)angular.forEach(g.rows[e],o)},u.$isSelected=function(e){return h.isSelected(e)},u.$setDisabledEl=function(e){e.disabled=h.isDisabled(e.date)},u.$selectPane=function(e){var t=h.steps,n=new Date(Date.UTC($.year+(t.year||0)*e,$.month+(t.month||0)*e,1));angular.extend($,{year:n.getUTCFullYear(),month:n.getUTCMonth(),date:n.getUTCDate()}),u.$build()},u.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),d){var t=angular.element(e.target);'button'!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler('click')}},u.$onKeyDown=function(e){if(/(38|37|39|40|13)/.test(e.keyCode)&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),e.stopPropagation(),13===e.keyCode)return g.$mode?g.$apply(function(){u.setMode(g.$mode-1)}):u.hide(!0);h.onKeyDown(e),f.$digest()}};var v=u.init;u.init=function(){return c&&p.useNative?(t.prop('type','date'),void t.css('-webkit-appearance','textfield')):(d&&(t.prop('type','text'),t.attr('readonly','true'),t.on('click',i)),void v())};var w=u.destroy;u.destroy=function(){c&&p.useNative&&t.off('click',i),w()};var y=u.show;u.show=function(){y(),l(function(){u.$isShown&&(u.$element.on(d?'touchstart':'mousedown',u.$onMouseDown),p.keyboard&&t.on('keydown',u.$onKeyDown))},0,!1)};var b=u.hide;return u.hide=function(e){u.$isShown&&(u.$element.off(d?'touchstart':'mousedown',u.$onMouseDown),p.keyboard&&t.off('keydown',u.$onKeyDown),b(e))},u}var c=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),d='createTouch'in t.document&&c;return e.lang||(e.lang=i.getDefaultLocale()),u.defaults=e,u}]}).directive('bsDatepicker',['$window','$parse','$q','$dateFormatter','$dateParser','$datepicker',function(e,t,n,a,o,i){var r=(i.defaults,/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent));return{restrict:'EAC',require:'ngModel',link:function(e,t,n,s){function l(e){return e&&e.length?e:null}function u(e){if(angular.isDate(e)){var t=isNaN(p.$options.minDate)||e.getTime()>=p.$options.minDate,n=isNaN(p.$options.maxDate)||e.getTime()<=p.$options.maxDate,a=t&&n;s.$setValidity('date',a),s.$setValidity('min',t),s.$setValidity('max',n),a&&(s.$dateValue=e)}}function c(){return!s.$dateValue||isNaN(s.$dateValue.getTime())?'':m(s.$dateValue,d.dateFormat)}var d={scope:e,controller:s};angular.forEach(['placement','container','delay','trigger','html','animation','template','autoclose','dateType','dateFormat','timezone','modelDateFormat','dayFormat','strictFormat','startWeek','startDate','useNative','lang','startView','minView','iconLeft','iconRight','daysOfWeekDisabled','id','prefixClass','prefixEvent'],function(e){angular.isDefined(n[e])&&(d[e]=n[e])});var f=/^(false|0|)$/i;angular.forEach(['html','container','autoclose','useNative'],function(e){angular.isDefined(n[e])&&f.test(n[e])&&(d[e]=!1)}),n.bsShow&&e.$watch(n.bsShow,function(e,t){p&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(datepicker),?/i)),e===!0?p.show():p.hide())});var p=i(t,s,d);d=p.$options,r&&d.useNative&&(d.dateFormat='yyyy-MM-dd');var g=d.lang,m=function(e,t){return a.formatDate(e,t,g)},$=o({format:d.dateFormat,lang:g,strict:d.strictFormat});angular.forEach(['minDate','maxDate'],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){p.$options[e]=$.getDateForAttribute(e,t),!isNaN(p.$options[e])&&p.$build(!1),u(s.$dateValue)})}),e.$watch(n.ngModel,function(e,t){p.update(s.$dateValue)},!0),angular.isDefined(n.disabledDates)&&e.$watch(n.disabledDates,function(e,t){e=l(e),t=l(t),e&&p.updateDisabledDates(e)}),s.$parsers.unshift(function(e){var t;if(!e)return s.$setValidity('date',!0),null;var n=$.parse(e,s.$dateValue);return!n||isNaN(n.getTime())?void s.$setValidity('date',!1):(u(n),'string'===d.dateType?(t=$.timezoneOffsetAdjust(n,d.timezone,!0),m(t,d.modelDateFormat||d.dateFormat)):(t=$.timezoneOffsetAdjust(s.$dateValue,d.timezone,!0),'number'===d.dateType?t.getTime():'unix'===d.dateType?t.getTime()/1e3:'iso'===d.dateType?t.toISOString():new Date(t)))}),s.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:'string'===d.dateType?$.parse(e,null,d.modelDateFormat):new Date('unix'===d.dateType?1e3*e:e),s.$dateValue=$.timezoneOffsetAdjust(t,d.timezone),c()}),s.$render=function(){t.val(c())},e.$on('$destroy',function(){p&&p.destroy(),d=null,p=null})}}}]).provider('datepickerViews',function(){function e(e,t){for(var n=[];e.length>0;)n.push(e.splice(0,t));return n}function t(e,t){return(e%t+t)%t}this.defaults={dayFormat:'dd',daySplit:7};this.$get=['$dateFormatter','$dateParser','$sce',function(n,a,o){return function(i){var r=i.$scope,s=i.$options,l=s.lang,u=function(e,t){return n.formatDate(e,t,l)},c=a({format:s.dateFormat,lang:l,strict:s.strictFormat}),d=n.weekdaysShort(l),f=d.slice(s.startWeek).concat(d.slice(0,s.startWeek)),p=o.trustAsHtml('<th class="dow text-center">'+f.join('</th><th class="dow text-center">')+'</th>'),g=i.$date||(s.startDate?c.getDateForAttribute('startDate',s.startDate):new Date),m={year:g.getFullYear(),month:g.getMonth(),date:g.getDate()},$=[{format:s.dayFormat,split:7,steps:{month:1},update:function(e,t){!this.built||t||e.getFullYear()!==m.year||e.getMonth()!==m.month?(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build()):(e.getDate()!==m.date||1===e.getDate())&&(m.date=i.$date.getDate(),i.$updateSelected())},build:function(){var n=new Date(m.year,m.month,1),a=n.getTimezoneOffset(),o=new Date(+n-864e5*t(n.getDay()-s.startWeek,7)),l=o.getTimezoneOffset(),d=c.timezoneOffsetAdjust(new Date,s.timezone).toDateString();l!==a&&(o=new Date(+o+6e4*(l-a)));for(var f,g=[],$=0;42>$;$++)f=c.daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth(),o.getDate()+$)),g.push({date:f,isToday:f.toDateString()===d,label:u(f,this.format),selected:i.$date&&this.isSelected(f),muted:f.getMonth()!==m.month,disabled:this.isDisabled(f)});r.title=u(n,s.monthTitleFormat),r.showLabels=!0,r.labels=p,r.rows=e(g,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()&&e.getMonth()===i.$date.getMonth()&&e.getDate()===i.$date.getDate()},isDisabled:function(e){var t=e.getTime();if(t<s.minDate||t>s.maxDate)return!0;if(-1!==s.daysOfWeekDisabled.indexOf(e.getDay()))return!0;if(s.disabledDateRanges)for(var n=0;n<s.disabledDateRanges.length;n++)if(t>=s.disabledDateRanges[n].start&&t<=s.disabledDateRanges[n].end)return!0;return!1},onKeyDown:function(e){if(i.$date){var t,n=i.$date.getTime();37===e.keyCode?t=new Date(n-864e5):38===e.keyCode?t=new Date(n-6048e5):39===e.keyCode?t=new Date(n+864e5):40===e.keyCode&&(t=new Date(n+6048e5)),this.isDisabled(t)||i.select(t,!0)}}},{name:'month',format:s.monthFormat,split:4,steps:{year:1},update:function(e,t){this.built&&e.getFullYear()===m.year?e.getMonth()!==m.month&&(angular.extend(m,{month:i.$date.getMonth(),date:i.$date.getDate()}),i.$updateSelected()):(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build())},build:function(){for(var t,n=(new Date(m.year,0,1),[]),a=0;12>a;a++)t=new Date(m.year,a,1),n.push({date:t,label:u(t,this.format),selected:i.$isSelected(t),disabled:this.isDisabled(t)});r.title=u(t,s.yearTitleFormat),r.showLabels=!1,r.rows=e(n,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()&&e.getMonth()===i.$date.getMonth()},isDisabled:function(e){var t=+new Date(e.getFullYear(),e.getMonth()+1,0);return t<s.minDate||e.getTime()>s.maxDate},onKeyDown:function(e){if(i.$date){var t=i.$date.getMonth(),n=new Date(i.$date);37===e.keyCode?n.setMonth(t-1):38===e.keyCode?n.setMonth(t-4):39===e.keyCode?n.setMonth(t+1):40===e.keyCode&&n.setMonth(t+4),this.isDisabled(n)||i.select(n,!0)}}},{name:'year',format:s.yearFormat,split:4,steps:{year:12},update:function(e,t){!this.built||t||parseInt(e.getFullYear()/20,10)!==parseInt(m.year/20,10)?(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build()):e.getFullYear()!==m.year&&(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$updateSelected())},build:function(){for(var t,n=m.year-m.year%(3*this.split),a=[],o=0;12>o;o++)t=new Date(n+o,0,1),a.push({date:t,label:u(t,this.format),selected:i.$isSelected(t),disabled:this.isDisabled(t)});r.title=a[0].label+'-'+a[a.length-1].label,r.showLabels=!1,r.rows=e(a,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()},isDisabled:function(e){var t=+new Date(e.getFullYear()+1,0,0);return t<s.minDate||e.getTime()>s.maxDate},onKeyDown:function(e){if(i.$date){var t=i.$date.getFullYear(),n=new Date(i.$date);37===e.keyCode?n.setYear(t-1):38===e.keyCode?n.setYear(t-4):39===e.keyCode?n.setYear(t+1):40===e.keyCode&&n.setYear(t+4),this.isDisabled(n)||i.select(n,!0)}}}];return{views:s.minView?Array.prototype.slice.call($,s.minView):$,viewDate:m}}}]}),angular.module('mgcrea.ngStrap.dropdown',['mgcrea.ngStrap.tooltip']).provider('$dropdown',function(){var e=this.defaults={animation:'am-fade',prefixClass:'dropdown',prefixEvent:'dropdown',placement:'bottom-left',template:'dropdown/dropdown.tpl.html',trigger:'click',container:!1,keyboard:!0,html:!1,delay:0};this.$get=['$window','$rootScope','$tooltip','$timeout',function(t,n,a,o){function i(t,i){function l(e){return e.target!==t[0]?e.target!==t[0]&&u.hide():void 0}{var u={},c=angular.extend({},e,i);u.$scope=c.scope&&c.scope.$new()||n.$new()}u=a(t,c);var d=t.parent();u.$onKeyDown=function(e){if(/(38|40)/.test(e.keyCode)){e.preventDefault(),e.stopPropagation();var t=angular.element(u.$element[0].querySelectorAll('li:not(.divider) a'));if(t.length){var n;angular.forEach(t,function(e,t){s&&s.call(e,':focus')&&(n=t)}),38===e.keyCode&&n>0?n--:40===e.keyCode&&n<t.length-1?n++:angular.isUndefined(n)&&(n=0),t.eq(n)[0].focus()}}};var f=u.show;u.show=function(){f(),o(function(){c.keyboard&&u.$element&&u.$element.on('keydown',u.$onKeyDown),r.on('click',l)},0,!1),d.hasClass('dropdown')&&d.addClass('open')};var p=u.hide;u.hide=function(){u.$isShown&&(c.keyboard&&u.$element&&u.$element.off('keydown',u.$onKeyDown),r.off('click',l),d.hasClass('dropdown')&&d.removeClass('open'),p())};var g=u.destroy;return u.destroy=function(){r.off('click',l),g()},u}var r=angular.element(t.document.body),s=Element.prototype.matchesSelector||Element.prototype.webkitMatchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector;return i}]}).directive('bsDropdown',['$window','$sce','$dropdown',function(e,t,n){return{restrict:'EAC',scope:!0,link:function(e,t,a,o){var i={scope:e};angular.forEach(['placement','container','delay','trigger','keyboard','html','animation','template','id'],function(e){angular.isDefined(a[e])&&(i[e]=a[e])});var r=/^(false|0|)$/i;angular.forEach(['html','container'],function(e){angular.isDefined(a[e])&&r.test(a[e])&&(i[e]=!1)}),a.bsDropdown&&e.$watch(a.bsDropdown,function(t,n){e.content=t},!0),a.bsShow&&e.$watch(a.bsShow,function(e,t){s&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(dropdown),?/i)),e===!0?s.show():s.hide())});var s=n(t,i);e.$on('$destroy',function(){s&&s.destroy(),i=null,s=null})}}}]),angular.module('mgcrea.ngStrap.button',[]).provider('$button',function(){var e=this.defaults={activeClass:'active',toggleEvent:'click'};this.$get=function(){return{defaults:e}}}).directive('bsCheckboxGroup',function(){return{restrict:'A',require:'ngModel',compile:function(e,t){e.attr('data-toggle','buttons'),e.removeAttr('ng-model');var n=e[0].querySelectorAll('input[type="checkbox"]');angular.forEach(n,function(e){var n=angular.element(e);n.attr('bs-checkbox',''),n.attr('ng-model',t.ngModel+'.'+n.attr('value'))})}}}).directive('bsCheckbox',['$button','$$rAF',function(e,t){var n=e.defaults,a=/^(true|false|\d+)$/;return{restrict:'A',require:'ngModel',link:function(e,o,i,r){var s=n,l='INPUT'===o[0].nodeName,u=l?o.parent():o,c=angular.isDefined(i.trueValue)?i.trueValue:!0;a.test(i.trueValue)&&(c=e.$eval(i.trueValue));var d=angular.isDefined(i.falseValue)?i.falseValue:!1;a.test(i.falseValue)&&(d=e.$eval(i.falseValue));var f='boolean'!=typeof c||'boolean'!=typeof d;f&&(r.$parsers.push(function(e){return e?c:d}),r.$formatters.push(function(e){return angular.equals(e,c)}),e.$watch(i.ngModel,function(e,t){r.$render()})),r.$render=function(){var e=angular.equals(r.$modelValue,c);t(function(){l&&(o[0].checked=e),u.toggleClass(s.activeClass,e)})},o.bind(s.toggleEvent,function(){e.$apply(function(){l||r.$setViewValue(!u.hasClass('active')),f||r.$render()})})}}}]).directive('bsRadioGroup',function(){return{restrict:'A',require:'ngModel',compile:function(e,t){e.attr('data-toggle','buttons'),e.removeAttr('ng-model');var n=e[0].querySelectorAll('input[type="radio"]');angular.forEach(n,function(e){angular.element(e).attr('bs-radio',''),angular.element(e).attr('ng-model',t.ngModel)})}}}).directive('bsRadio',['$button','$$rAF',function(e,t){var n=e.defaults,a=/^(true|false|\d+)$/;return{restrict:'A',require:'ngModel',link:function(e,o,i,r){var s,l=n,u='INPUT'===o[0].nodeName,c=u?o.parent():o;i.$observe('value',function(t){s=a.test(t)?e.$eval(t):t,r.$render()}),r.$render=function(){var e=angular.equals(r.$modelValue,s);t(function(){u&&(o[0].checked=e),c.toggleClass(l.activeClass,e)})},o.bind(l.toggleEvent,function(){e.$apply(function(){r.$setViewValue(s),r.$render()})})}}}]),angular.module('mgcrea.ngStrap.helpers.dateFormatter',[]).service('$dateFormatter',['$locale','dateFilter',function(e,t){function n(e){return/(h+)([:\.])?(m+)([:\.])?(s*)[ ]?(a?)/i.exec(e).slice(1)}this.getDefaultLocale=function(){return e.id},this.getDatetimeFormat=function(t,n){return e.DATETIME_FORMATS[t]||t},this.weekdaysShort=function(t){return e.DATETIME_FORMATS.SHORTDAY},this.hoursFormat=function(e){return n(e)[0]},this.minutesFormat=function(e){return n(e)[2]},this.secondsFormat=function(e){return n(e)[4]},this.timeSeparator=function(e){return n(e)[1]},this.showSeconds=function(e){return!!n(e)[4]},this.showAM=function(e){return!!n(e)[5]},this.formatDate=function(e,n,a,o){return t(e,n,o)}}]),angular.module('mgcrea.ngStrap.helpers.dateParser',[]).provider('$dateParser',['$localeProvider',function(e){function t(){this.year=1970,this.month=0,this.day=1,this.hours=0,this.minutes=0,this.seconds=0,this.milliseconds=0}function n(){}function a(e){return!isNaN(parseFloat(e))&&isFinite(e)}function o(e,t){for(var n=e.length,a=t.toString().toLowerCase(),o=0;n>o;o++)if(e[o].toLowerCase()===a)return o;return-1}t.prototype.setMilliseconds=function(e){this.milliseconds=e},t.prototype.setSeconds=function(e){this.seconds=e},t.prototype.setMinutes=function(e){this.minutes=e},t.prototype.setHours=function(e){this.hours=e},t.prototype.getHours=function(){return this.hours},t.prototype.setDate=function(e){this.day=e},t.prototype.setMonth=function(e){this.month=e},t.prototype.setFullYear=function(e){this.year=e},t.prototype.fromDate=function(e){return this.year=e.getFullYear(),this.month=e.getMonth(),this.day=e.getDate(),this.hours=e.getHours(),this.minutes=e.getMinutes(),this.seconds=e.getSeconds(),this.milliseconds=e.getMilliseconds(),this},t.prototype.toDate=function(){return new Date(this.year,this.month,this.day,this.hours,this.minutes,this.seconds,this.milliseconds)};var i=t.prototype,r=this.defaults={format:'shortDate',strict:!1};this.$get=['$locale','dateFilter',function(e,s){var l=function(l){function u(e){var t,n=Object.keys(h),a=[],o=[],i=e;for(t=0;t<n.length;t++)if(e.split(n[t]).length>1){var r=i.search(n[t]);e=e.split(n[t]).join(''),h[n[t]]&&(a[r]=h[n[t]])}return angular.forEach(a,function(e){e&&o.push(e)}),o}function c(e){return e.replace(/\//g,'[\\/]').replace('/-/g','[-]').replace(/\./g,'[.]').replace(/\\s/g,'[\\s]')}function d(e){var t,n=Object.keys($),a=e;for(t=0;t<n.length;t++)a=a.split(n[t]).join('${'+t+'}');for(t=0;t<n.length;t++)a=a.split('${'+t+'}').join('('+$[n[t]]+')');return e=c(e),new RegExp('^'+a+'$',['i'])}var f,p,g=angular.extend({},r,l),m={},$={sss:'[0-9]{3}',ss:'[0-5][0-9]',s:g.strict?'[1-5]?[0-9]':'[0-9]|[0-5][0-9]',mm:'[0-5][0-9]',m:g.strict?'[1-5]?[0-9]':'[0-9]|[0-5][0-9]',HH:'[01][0-9]|2[0-3]',H:g.strict?'1?[0-9]|2[0-3]':'[01]?[0-9]|2[0-3]',hh:'[0][1-9]|[1][012]',h:g.strict?'[1-9]|1[012]':'0?[1-9]|1[012]',a:'AM|PM',EEEE:e.DATETIME_FORMATS.DAY.join('|'),EEE:e.DATETIME_FORMATS.SHORTDAY.join('|'),dd:'0[1-9]|[12][0-9]|3[01]',d:g.strict?'[1-9]|[1-2][0-9]|3[01]':'0?[1-9]|[1-2][0-9]|3[01]',MMMM:e.DATETIME_FORMATS.MONTH.join('|'),MMM:e.DATETIME_FORMATS.SHORTMONTH.join('|'),MM:'0[1-9]|1[012]',M:g.strict?'[1-9]|1[012]':'0?[1-9]|1[012]',yyyy:'[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',yy:'[0-9]{2}',y:g.strict?'-?(0|[1-9][0-9]{0,3})':'-?0*[0-9]{1,4}'},h={sss:i.setMilliseconds,ss:i.setSeconds,s:i.setSeconds,mm:i.setMinutes,m:i.setMinutes,HH:i.setHours,H:i.setHours,hh:i.setHours,h:i.setHours,EEEE:n,EEE:n,dd:i.setDate,d:i.setDate,a:function(e){var t=this.getHours()%12;return this.setHours(e.match(/pm/i)?t+12:t)},MMMM:function(t){return this.setMonth(o(e.DATETIME_FORMATS.MONTH,t))},MMM:function(t){return this.setMonth(o(e.DATETIME_FORMATS.SHORTMONTH,t))},MM:function(e){return this.setMonth(1*e-1)},M:function(e){return this.setMonth(1*e-1)},yyyy:i.setFullYear,yy:function(e){return this.setFullYear(2e3+1*e)},y:i.setFullYear};return m.init=function(){m.$format=e.DATETIME_FORMATS[g.format]||g.format,f=d(m.$format),p=u(m.$format)},m.isValid=function(e){return angular.isDate(e)?!isNaN(e.getTime()):f.test(e)},m.parse=function(n,a,o,i){o&&(o=e.DATETIME_FORMATS[o]||o),angular.isDate(n)&&(n=s(n,o||m.$format,i));var r=o?d(o):f,l=o?u(o):p,c=r.exec(n);if(!c)return!1;for(var g=(new t).fromDate(a&&!isNaN(a.getTime())?a:new Date(1970,0,1,0)),$=0;$<c.length-1;$++)l[$]&&l[$].call(g,c[$+1]);var h=g.toDate();return parseInt(g.day,10)!==h.getDate()?!1:h},m.getDateForAttribute=function(e,t){var n;if('today'===t){var o=new Date;n=new Date(o.getFullYear(),o.getMonth(),o.getDate()+('maxDate'===e?1:0),0,0,0,'minDate'===e?0:-1)}else n=angular.isString(t)&&t.match(/^".+"$/)?new Date(t.substr(1,t.length-2)):a(t)?new Date(parseInt(t,10)):angular.isString(t)&&0===t.length?'minDate'===e?-(1/0):+(1/0):new Date(t);return n},m.getTimeForAttribute=function(e,t){var n;return n='now'===t?(new Date).setFullYear(1970,0,1):angular.isString(t)&&t.match(/^".+"$/)?new Date(t.substr(1,t.length-2)).setFullYear(1970,0,1):a(t)?new Date(parseInt(t,10)).setFullYear(1970,0,1):angular.isString(t)&&0===t.length?'minTime'===e?-(1/0):+(1/0):m.parse(t,new Date(1970,0,1,0))},m.daylightSavingAdjust=function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},m.timezoneOffsetAdjust=function(e,t,n){return e?(t&&'UTC'===t&&(e=new Date(e.getTime()),e.setMinutes(e.getMinutes()+(n?-1:1)*e.getTimezoneOffset())),e):null},m.init(),m};return l}]}]),angular.module('mgcrea.ngStrap.helpers.debounce',[]).factory('debounce',['$timeout',function(e){return function(t,n,a){var o=null;return function(){var i=this,r=arguments,s=a&&!o;return o&&e.cancel(o),o=e(function(){o=null,a||t.apply(i,r)},n,!1),s&&t.apply(i,r),o}}}]).factory('throttle',['$timeout',function(e){return function(t,n,a){var o=null;return a||(a={}),function(){var i=this,r=arguments;o||(a.leading!==!1&&t.apply(i,r),o=e(function(){o=null,a.trailing!==!1&&t.apply(i,r)},n,!1))}}}]),angular.module('mgcrea.ngStrap.helpers.dimensions',[]).factory('dimensions',['$document','$window',function(t,n){var a=(angular.element,{}),o=a.nodeName=function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()};a.css=function(t,n,a){var o;return o=t.currentStyle?t.currentStyle[n]:e.getComputedStyle?e.getComputedStyle(t)[n]:t.style[n],a===!0?parseFloat(o)||0:o},a.offset=function(t){var n=t.getBoundingClientRect(),a=t.ownerDocument;return{width:n.width||t.offsetWidth,height:n.height||t.offsetHeight,top:n.top+(e.pageYOffset||a.documentElement.scrollTop)-(a.documentElement.clientTop||0),left:n.left+(e.pageXOffset||a.documentElement.scrollLeft)-(a.documentElement.clientLeft||0)}},a.setOffset=function(e,t,n){var o,i,r,s,l,u,c,d=a.css(e,'position'),f=angular.element(e),p={};'static'===d&&(e.style.position='relative'),l=a.offset(e),r=a.css(e,'top'),u=a.css(e,'left'),c=('absolute'===d||'fixed'===d)&&(r+u).indexOf('auto')>-1,c?(o=a.position(e),s=o.top,i=o.left):(s=parseFloat(r)||0,i=parseFloat(u)||0),angular.isFunction(t)&&(t=t.call(e,n,l)),
9
+ null!==t.top&&(p.top=t.top-l.top+s),null!==t.left&&(p.left=t.left-l.left+i),'using'in t?t.using.call(f,p):f.css({top:p.top+'px',left:p.left+'px'})},a.position=function(e){var t,n,r={top:0,left:0};return'fixed'===a.css(e,'position')?n=e.getBoundingClientRect():(t=i(e),n=a.offset(e),o(t,'html')||(r=a.offset(t)),r.top+=a.css(t,'borderTopWidth',!0),r.left+=a.css(t,'borderLeftWidth',!0)),{width:e.offsetWidth,height:e.offsetHeight,top:n.top-r.top-a.css(e,'marginTop',!0),left:n.left-r.left-a.css(e,'marginLeft',!0)}};var i=function(e){var t=e.ownerDocument,n=e.offsetParent||t;if(o(n,'#document'))return t.documentElement;for(;n&&!o(n,'html')&&'static'===a.css(n,'position');)n=n.offsetParent;return n||t.documentElement};return a.height=function(e,t){var n=e.offsetHeight;return t?n+=a.css(e,'marginTop',!0)+a.css(e,'marginBottom',!0):n-=a.css(e,'paddingTop',!0)+a.css(e,'paddingBottom',!0)+a.css(e,'borderTopWidth',!0)+a.css(e,'borderBottomWidth',!0),n},a.width=function(e,t){var n=e.offsetWidth;return t?n+=a.css(e,'marginLeft',!0)+a.css(e,'marginRight',!0):n-=a.css(e,'paddingLeft',!0)+a.css(e,'paddingRight',!0)+a.css(e,'borderLeftWidth',!0)+a.css(e,'borderRightWidth',!0),n},a}]),angular.module('mgcrea.ngStrap.helpers.parseOptions',[]).provider('$parseOptions',function(){var e=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+(.*?))?$/};this.$get=['$parse','$q',function(t,n){function a(a,o){function i(e,t){return e.map(function(e,n){var a,o,i={};return i[c]=e,a=u(t,i),o=p(t,i),{label:a,value:o,index:n}})}var r={},s=angular.extend({},e,o);r.$values=[];var l,u,c,d,f,p,g;return r.init=function(){r.$match=l=a.match(s.regexp),u=t(l[2]||l[1]),c=l[4]||l[6],d=l[5],f=t(l[3]||''),p=t(l[2]?l[1]:c),g=t(l[7])},r.valuesFn=function(e,t){return n.when(g(e,t)).then(function(t){return r.$values=t?i(t,e):{},r.$values})},r.displayValue=function(e){var t={};return t[c]=e,u(t)},r.init(),r}return a}]}),angular.version.minor<3&&angular.version.dot<14&&angular.module('ng').factory('$$rAF',['$window','$timeout',function(e,t){var n=e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame,a=e.cancelAnimationFrame||e.webkitCancelAnimationFrame||e.mozCancelAnimationFrame||e.webkitCancelRequestAnimationFrame,o=!!n,i=o?function(e){var t=n(e);return function(){a(t)}}:function(e){var n=t(e,16.66,!1);return function(){t.cancel(n)}};return i.supported=o,i}]),angular.module('mgcrea.ngStrap.modal',['mgcrea.ngStrap.helpers.dimensions']).provider('$modal',function(){var e=this.defaults={animation:'am-fade',backdropAnimation:'am-fade',prefixClass:'modal',prefixEvent:'modal',placement:'top',template:'modal/modal.tpl.html',contentTemplate:!1,container:!1,element:null,backdrop:!0,keyboard:!0,html:!1,show:!0};this.$get=['$window','$rootScope','$compile','$q','$templateCache','$http','$animate','$timeout','$sce','dimensions',function(n,a,o,i,r,s,l,u,c,d){function f(t){function n(){f.$emit(d.prefixEvent+'.show',u)}function i(){f.$emit(d.prefixEvent+'.hide',u),w.removeClass(d.prefixClass+'-open'),d.animation&&w.removeClass(d.prefixClass+'-with-'+d.animation)}function r(e){e.target===e.currentTarget&&('static'===d.backdrop?u.focus():u.hide())}function s(e){e.preventDefault()}var u={},d=u.$options=angular.extend({},e,t);u.$promise=m(d.template);var f=u.$scope=d.scope&&d.scope.$new()||a.$new();d.element||d.container||(d.container='body'),u.$id=d.id||d.element&&d.element.attr('id')||'',$(['title','content'],function(e){d[e]&&(f[e]=c.trustAsHtml(d[e]))}),f.$hide=function(){f.$$postDigest(function(){u.hide()})},f.$show=function(){f.$$postDigest(function(){u.show()})},f.$toggle=function(){f.$$postDigest(function(){u.toggle()})},u.$isShown=f.$isShown=!1,d.contentTemplate&&(u.$promise=u.$promise.then(function(e){var n=angular.element(e);return m(d.contentTemplate).then(function(e){var a=g('[ng-bind="content"]',n[0]).removeAttr('ng-bind').html(e);return t.template||a.next().remove(),n[0].outerHTML})}));var b,D,k=angular.element('<div class="'+d.prefixClass+'-backdrop"/>');return k.css({position:'fixed',top:'0px',left:'0px',bottom:'0px',right:'0px','z-index':1038}),u.$promise.then(function(e){angular.isObject(e)&&(e=e.data),d.html&&(e=e.replace(y,'ng-bind-html="')),e=h.apply(e),b=o(e),u.init()}),u.init=function(){d.show&&f.$$postDigest(function(){u.show()})},u.destroy=function(){D&&(D.remove(),D=null),k&&(k.remove(),k=null),f.$destroy()},u.show=function(){if(!u.$isShown){var e,t;if(angular.isElement(d.container)?(e=d.container,t=d.container[0].lastChild?angular.element(d.container[0].lastChild):null):d.container?(e=g(d.container),t=e[0]&&e[0].lastChild?angular.element(e[0].lastChild):null):(e=null,t=d.element),D=u.$element=b(f,function(e,t){}),!f.$emit(d.prefixEvent+'.show.before',u).defaultPrevented){D.css({display:'block'}).addClass(d.placement),d.animation&&(d.backdrop&&k.addClass(d.backdropAnimation),D.addClass(d.animation)),d.backdrop&&l.enter(k,w,null),angular.version.minor<=2?l.enter(D,e,t,n):l.enter(D,e,t).then(n),u.$isShown=f.$isShown=!0,p(f);var a=D[0];v(function(){a.focus()}),w.addClass(d.prefixClass+'-open'),d.animation&&w.addClass(d.prefixClass+'-with-'+d.animation),d.backdrop&&(D.on('click',r),k.on('click',r),k.on('wheel',s)),d.keyboard&&D.on('keyup',u.$onKeyUp)}}},u.hide=function(){u.$isShown&&(f.$emit(d.prefixEvent+'.hide.before',u).defaultPrevented||(angular.version.minor<=2?l.leave(D,i):l.leave(D).then(i),d.backdrop&&l.leave(k),u.$isShown=f.$isShown=!1,p(f),d.backdrop&&(D.off('click',r),k.off('click',r),k.off('wheel',s)),d.keyboard&&D.off('keyup',u.$onKeyUp)))},u.toggle=function(){u.$isShown?u.hide():u.show()},u.focus=function(){D[0].focus()},u.$onKeyUp=function(e){27===e.which&&u.$isShown&&(u.hide(),e.stopPropagation())},u}function p(e){e.$$phase||e.$root&&e.$root.$$phase||e.$digest()}function g(e,n){return angular.element((n||t).querySelectorAll(e))}function m(e){return b[e]?b[e]:b[e]=s.get(e,{cache:r}).then(function(e){return e.data})}var $=angular.forEach,h=String.prototype.trim,v=n.requestAnimationFrame||n.setTimeout,w=angular.element(n.document.body),y=/ng-bind="/gi,b={};return f}]}).directive('bsModal',['$window','$sce','$modal',function(e,t,n){return{restrict:'EAC',scope:!0,link:function(e,a,o,i){var r={scope:e,element:a,show:!1};angular.forEach(['template','contentTemplate','placement','backdrop','keyboard','html','container','animation','id','prefixEvent','prefixClass'],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var s=/^(false|0|)$/i;angular.forEach(['backdrop','keyboard','html','container'],function(e){angular.isDefined(o[e])&&s.test(o[e])&&(r[e]=!1)}),angular.forEach(['title','content'],function(n){o[n]&&o.$observe(n,function(a,o){e[n]=t.trustAsHtml(a)})}),o.bsModal&&e.$watch(o.bsModal,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var l=n(r);a.on(o.trigger||'click',l.toggle),e.$on('$destroy',function(){l&&l.destroy(),r=null,l=null})}}}]),angular.module('mgcrea.ngStrap.navbar',[]).provider('$navbar',function(){var e=this.defaults={activeClass:'active',routeAttr:'data-match-route',strict:!1};this.$get=function(){return{defaults:e}}}).directive('bsNavbar',['$window','$location','$navbar',function(e,t,n){var a=n.defaults;return{restrict:'A',link:function(e,n,o,i){var r=angular.copy(a);angular.forEach(Object.keys(a),function(e){angular.isDefined(o[e])&&(r[e]=o[e])}),e.$watch(function(){return t.path()},function(e,t){var a=n[0].querySelectorAll('li['+r.routeAttr+']');angular.forEach(a,function(t){var n=angular.element(t),a=n.attr(r.routeAttr).replace('/','\\/');r.strict&&(a='^'+a+'$');var o=new RegExp(a,'i');o.test(e)?n.addClass(r.activeClass):n.removeClass(r.activeClass)})})}}}]),angular.module('mgcrea.ngStrap.popover',['mgcrea.ngStrap.tooltip']).provider('$popover',function(){var e=this.defaults={animation:'am-fade',customClass:'',container:!1,target:!1,placement:'right',template:'popover/popover.tpl.html',contentTemplate:!1,trigger:'click',keyboard:!0,html:!1,title:'',content:'',delay:0,autoClose:!1};this.$get=['$tooltip',function(t){function n(n,a){var o=angular.extend({},e,a),i=t(n,o);return o.content&&(i.$scope.content=o.content),i}return n}]}).directive('bsPopover',['$window','$sce','$popover',function(e,t,n){var a=e.requestAnimationFrame||e.setTimeout;return{restrict:'EAC',scope:!0,link:function(e,o,i){var r={scope:e};angular.forEach(['template','contentTemplate','placement','container','delay','trigger','html','animation','customClass','autoClose','id','prefixClass','prefixEvent'],function(e){angular.isDefined(i[e])&&(r[e]=i[e])});var s=/^(false|0|)$/i;angular.forEach(['html','container','autoClose'],function(e){angular.isDefined(i[e])&&s.test(i[e])&&(r[e]=!1)});var l=o.attr('data-target');angular.isDefined(l)&&(r.target=s.test(l)?!1:l),angular.forEach(['title','content'],function(n){i[n]&&i.$observe(n,function(o,i){e[n]=t.trustAsHtml(o),angular.isDefined(i)&&a(function(){u&&u.$applyPlacement()})})}),i.bsPopover&&e.$watch(i.bsPopover,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t,angular.isDefined(n)&&a(function(){u&&u.$applyPlacement()})},!0),i.bsShow&&e.$watch(i.bsShow,function(e,t){u&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(popover),?/i)),e===!0?u.show():u.hide())}),i.viewport&&e.$watch(i.viewport,function(e){u&&angular.isDefined(e)&&u.setViewport(e)});var u=n(o,r);e.$on('$destroy',function(){u&&u.destroy(),r=null,u=null})}}}]),angular.module('mgcrea.ngStrap.scrollspy',['mgcrea.ngStrap.helpers.debounce','mgcrea.ngStrap.helpers.dimensions']).provider('$scrollspy',function(){var e=this.$$spies={},n=this.defaults={debounce:150,throttle:100,offset:100};this.$get=['$window','$document','$rootScope','dimensions','debounce','throttle',function(a,o,i,r,s,l){function u(e,t){return e[0].nodeName&&e[0].nodeName.toLowerCase()===t.toLowerCase()}function c(o){var c=angular.extend({},n,o);c.element||(c.element=p);var g=u(c.element,'body'),m=g?d:c.element,$=g?'window':c.id;if(e[$])return e[$].$$count++,e[$];var h,v,w,y,b,D,k,S,x={},T=x.$trackedElements=[],C=[];return x.init=function(){this.$$count=1,y=s(this.checkPosition,c.debounce),b=l(this.checkPosition,c.throttle),m.on('click',this.checkPositionWithEventLoop),d.on('resize',y),m.on('scroll',b),D=s(this.checkOffsets,c.debounce),h=i.$on('$viewContentLoaded',D),v=i.$on('$includeContentLoaded',D),D(),$&&(e[$]=x)},x.destroy=function(){this.$$count--,this.$$count>0||(m.off('click',this.checkPositionWithEventLoop),d.off('resize',y),m.off('scroll',b),h(),v(),$&&delete e[$])},x.checkPosition=function(){if(C.length){if(S=(g?a.pageYOffset:m.prop('scrollTop'))||0,k=Math.max(a.innerHeight,f.prop('clientHeight')),S<C[0].offsetTop&&w!==C[0].target)return x.$activateElement(C[0]);for(var e=C.length;e--;)if(!angular.isUndefined(C[e].offsetTop)&&null!==C[e].offsetTop&&w!==C[e].target&&!(S<C[e].offsetTop||C[e+1]&&S>C[e+1].offsetTop))return x.$activateElement(C[e])}},x.checkPositionWithEventLoop=function(){setTimeout(x.checkPosition,1)},x.$activateElement=function(e){if(w){var t=x.$getTrackedElement(w);t&&(t.source.removeClass('active'),u(t.source,'li')&&u(t.source.parent().parent(),'li')&&t.source.parent().parent().removeClass('active'))}w=e.target,e.source.addClass('active'),u(e.source,'li')&&u(e.source.parent().parent(),'li')&&e.source.parent().parent().addClass('active')},x.$getTrackedElement=function(e){return T.filter(function(t){return t.target===e})[0]},x.checkOffsets=function(){angular.forEach(T,function(e){var n=t.querySelector(e.target);e.offsetTop=n?r.offset(n).top:null,c.offset&&null!==e.offsetTop&&(e.offsetTop-=1*c.offset)}),C=T.filter(function(e){return null!==e.offsetTop}).sort(function(e,t){return e.offsetTop-t.offsetTop}),y()},x.trackElement=function(e,t){T.push({target:e,source:t})},x.untrackElement=function(e,t){for(var n,a=T.length;a--;)if(T[a].target===e&&T[a].source===t){n=a;break}T=T.splice(n,1)},x.activate=function(e){T[e].addClass('active')},x.init(),x}var d=angular.element(a),f=angular.element(o.prop('documentElement')),p=angular.element(a.document.body);return c}]}).directive('bsScrollspy',['$rootScope','debounce','dimensions','$scrollspy',function(e,t,n,a){return{restrict:'EAC',link:function(e,t,n){var o={scope:e};angular.forEach(['offset','target'],function(e){angular.isDefined(n[e])&&(o[e]=n[e])});var i=a(o);i.trackElement(o.target,t),e.$on('$destroy',function(){i&&(i.untrackElement(o.target,t),i.destroy()),o=null,i=null})}}}]).directive('bsScrollspyList',['$rootScope','debounce','dimensions','$scrollspy',function(e,t,n,a){return{restrict:'A',compile:function(e,t){var n=e[0].querySelectorAll('li > a[href]');angular.forEach(n,function(e){var t=angular.element(e);t.parent().attr('bs-scrollspy','').attr('data-target',t.attr('href'))})}}}]),angular.module('mgcrea.ngStrap.select',['mgcrea.ngStrap.tooltip','mgcrea.ngStrap.helpers.parseOptions']).provider('$select',function(){var e=this.defaults={animation:'am-fade',prefixClass:'select',prefixEvent:'$select',placement:'bottom-left',template:'select/select.tpl.html',trigger:'focus',container:!1,keyboard:!0,html:!1,delay:0,multiple:!1,allNoneButtons:!1,sort:!0,caretHtml:'&nbsp;<span class="caret"></span>',placeholder:'Choose among the following...',allText:'All',noneText:'None',maxLength:3,maxLengthHtml:'selected',iconCheckmark:'glyphicon glyphicon-ok'};this.$get=['$window','$document','$rootScope','$tooltip','$timeout',function(t,n,a,o,i){function r(t,n,a){var r={},s=angular.extend({},e,a);r=o(t,s);var u=r.$scope;u.$matches=[],u.$activeIndex=s.multiple?[]:-1,u.$isMultiple=s.multiple,u.$showAllNoneButtons=s.allNoneButtons&&s.multiple,u.$iconCheckmark=s.iconCheckmark,u.$allText=s.allText,u.$noneText=s.noneText,u.$activate=function(e){u.$$postDigest(function(){r.activate(e)})},u.$select=function(e,t){u.$$postDigest(function(){r.select(e)})},u.$isVisible=function(){return r.$isVisible()},u.$isActive=function(e){return r.$isActive(e)},u.$selectAll=function(){for(var e=0;e<u.$matches.length;e++)u.$isActive(e)||u.$select(e)},u.$selectNone=function(){for(var e=0;e<u.$matches.length;e++)u.$isActive(e)&&u.$select(e)},r.update=function(e){u.$matches=e,r.$updateActiveIndex()},r.activate=function(e){return s.multiple?(r.$isActive(e)?u.$activeIndex.splice(u.$activeIndex.indexOf(e),1):u.$activeIndex.push(e),s.sort&&u.$activeIndex.sort(function(e,t){return e-t})):u.$activeIndex=e,u.$activeIndex},r.select=function(e){var t=u.$matches[e].value;u.$apply(function(){r.activate(e),s.multiple?n.$setViewValue(u.$activeIndex.map(function(e){return u.$matches[e].value})):(n.$setViewValue(t),r.hide())}),u.$emit(s.prefixEvent+'.select',t,e,r)},r.$updateActiveIndex=function(){n.$modelValue&&u.$matches.length?u.$activeIndex=s.multiple&&angular.isArray(n.$modelValue)?n.$modelValue.map(function(e){return r.$getIndex(e)}):r.$getIndex(n.$modelValue):u.$activeIndex>=u.$matches.length&&(u.$activeIndex=s.multiple?[]:0)},r.$isVisible=function(){return s.minLength&&n?u.$matches.length&&n.$viewValue.length>=s.minLength:u.$matches.length},r.$isActive=function(e){return s.multiple?-1!==u.$activeIndex.indexOf(e):u.$activeIndex===e},r.$getIndex=function(e){var t=u.$matches.length,n=t;if(t){for(n=t;n--&&u.$matches[n].value!==e;);if(!(0>n))return n}},r.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),l){var t=angular.element(e.target);t.triggerHandler('click')}},r.$onKeyDown=function(e){return/(9|13|38|40)/.test(e.keyCode)?(e.preventDefault(),e.stopPropagation(),s.multiple&&9===e.keyCode?r.hide():s.multiple||13!==e.keyCode&&9!==e.keyCode?void(s.multiple||(38===e.keyCode&&u.$activeIndex>0?u.$activeIndex--:38===e.keyCode&&u.$activeIndex<0?u.$activeIndex=u.$matches.length-1:40===e.keyCode&&u.$activeIndex<u.$matches.length-1?u.$activeIndex++:angular.isUndefined(u.$activeIndex)&&(u.$activeIndex=0),u.$digest())):r.select(u.$activeIndex)):void 0};var c=r.show;r.show=function(){c(),s.multiple&&r.$element.addClass('select-multiple'),i(function(){r.$element.on(l?'touchstart':'mousedown',r.$onMouseDown),s.keyboard&&t.on('keydown',r.$onKeyDown)},0,!1)};var d=r.hide;return r.hide=function(){s.multiple||n.$modelValue||(u.$activeIndex=-1),r.$element.off(l?'touchstart':'mousedown',r.$onMouseDown),s.keyboard&&t.off('keydown',r.$onKeyDown),d(!0)},r}var s=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),l='createTouch'in t.document&&s;return r.defaults=e,r}]}).directive('bsSelect',['$window','$parse','$q','$select','$parseOptions',function(e,t,n,a,o){var i=a.defaults;return{restrict:'EAC',require:'ngModel',link:function(e,t,n,r){var s={scope:e,placeholder:i.placeholder};angular.forEach(['placement','container','delay','trigger','keyboard','html','animation','template','placeholder','allNoneButtons','maxLength','maxLengthHtml','allText','noneText','iconCheckmark','autoClose','id','sort','caretHtml','prefixClass','prefixEvent'],function(e){angular.isDefined(n[e])&&(s[e]=n[e])});var l=/^(false|0|)$/i;angular.forEach(['html','container','allNoneButtons','sort'],function(e){angular.isDefined(n[e])&&l.test(n[e])&&(s[e]=!1)});var u=t.attr('data-multiple');if(angular.isDefined(u)&&(s.multiple=l.test(u)?!1:u),'select'===t[0].nodeName.toLowerCase()){var c=t;c.css('display','none'),t=angular.element('<button type="button" class="btn btn-default"></button>'),c.after(t)}var d=o(n.bsOptions),f=a(t,r,s),p=d.$match[7].replace(/\|.+/,'').trim();e.$watchCollection(p,function(t,n){d.valuesFn(e,r).then(function(e){f.update(e),r.$render()})}),e.$watch(n.ngModel,function(e,t){f.$updateActiveIndex(),r.$render()},!0),r.$render=function(){var e,n;s.multiple&&angular.isArray(r.$modelValue)?(e=r.$modelValue.map(function(e){return n=f.$getIndex(e),angular.isDefined(n)?f.$scope.$matches[n].label:!1}).filter(angular.isDefined),e=e.length>(s.maxLength||i.maxLength)?e.length+' '+(s.maxLengthHtml||i.maxLengthHtml):e.join(', ')):(n=f.$getIndex(r.$modelValue),e=angular.isDefined(n)?f.$scope.$matches[n].label:!1),t.html((e?e:s.placeholder)+(s.caretHtml?s.caretHtml:i.caretHtml))},s.multiple&&(r.$isEmpty=function(e){return!e||0===e.length}),e.$on('$destroy',function(){f&&f.destroy(),s=null,f=null})}}}]),angular.module('mgcrea.ngStrap.tab',[]).provider('$tab',function(){var e=this.defaults={animation:'am-fade',template:'tab/tab.tpl.html',navClass:'nav-tabs',activeClass:'active'},t=this.controller=function(t,n,a){var o=this;o.$options=angular.copy(e),angular.forEach(['animation','navClass','activeClass'],function(e){angular.isDefined(a[e])&&(o.$options[e]=a[e])}),t.$navClass=o.$options.navClass,t.$activeClass=o.$options.activeClass,o.$panes=t.$panes=[],o.$activePaneChangeListeners=o.$viewChangeListeners=[],o.$push=function(e){angular.isUndefined(o.$panes.$active)&&t.$setActive(e.name||0),o.$panes.push(e)},o.$remove=function(e){var t,n=o.$panes.indexOf(e),a=o.$panes.$active;t=angular.isString(a)?o.$panes.map(function(e){return e.name}).indexOf(a):o.$panes.$active,o.$panes.splice(n,1),t>n?t--:n===t&&t===o.$panes.length&&t--,t>=0&&t<o.$panes.length?o.$setActive(o.$panes[t].name||t):o.$setActive()},o.$setActive=t.$setActive=function(e){o.$panes.$active=e,o.$activePaneChangeListeners.forEach(function(e){e()})},o.$isActive=t.$isActive=function(e,t){return o.$panes.$active===e.name||o.$panes.$active===t}};this.$get=function(){var n={};return n.defaults=e,n.controller=t,n}}).directive('bsTabs',['$window','$animate','$tab','$parse',function(e,t,n,a){var o=n.defaults;return{require:['?ngModel','bsTabs'],transclude:!0,scope:!0,controller:['$scope','$element','$attrs',n.controller],templateUrl:function(e,t){return t.template||o.template},link:function(e,t,n,o){var i=o[0],r=o[1];if(i&&(r.$activePaneChangeListeners.push(function(){i.$setViewValue(r.$panes.$active)}),i.$formatters.push(function(e){return r.$setActive(e),e})),n.bsActivePane){var s=a(n.bsActivePane);r.$activePaneChangeListeners.push(function(){s.assign(e,r.$panes.$active)}),e.$watch(n.bsActivePane,function(e,t){r.$setActive(e)},!0)}}}}]).directive('bsPane',['$window','$animate','$sce',function(e,t,n){return{require:['^?ngModel','^bsTabs'],scope:!0,link:function(e,a,o,i){function r(){var n=s.$panes.indexOf(e);t[s.$isActive(e,n)?'addClass':'removeClass'](a,s.$options.activeClass)}var s=(i[0],i[1]);a.addClass('tab-pane'),o.$observe('title',function(t,a){e.title=n.trustAsHtml(t)}),e.name=o.name,s.$options.animation&&a.addClass(s.$options.animation),o.$observe('disabled',function(t,n){e.disabled=e.$eval(t)}),s.$push(e),e.$on('$destroy',function(){s.$remove(e)}),s.$activePaneChangeListeners.push(function(){r()}),r()}}}]),angular.module('mgcrea.ngStrap.timepicker',['mgcrea.ngStrap.helpers.dateParser','mgcrea.ngStrap.helpers.dateFormatter','mgcrea.ngStrap.tooltip']).provider('$timepicker',function(){var e=this.defaults={animation:'am-fade',prefixClass:'timepicker',placement:'bottom-left',template:'timepicker/timepicker.tpl.html',trigger:'focus',container:!1,keyboard:!0,html:!1,delay:0,useNative:!0,timeType:'date',timeFormat:'shortTime',timezone:null,modelTimeFormat:null,autoclose:!1,minTime:-(1/0),maxTime:+(1/0),length:5,hourStep:1,minuteStep:5,secondStep:5,roundDisplay:!1,iconUp:'glyphicon glyphicon-chevron-up',iconDown:'glyphicon glyphicon-chevron-down',arrowBehavior:'pager'};this.$get=['$window','$document','$rootScope','$sce','$dateFormatter','$tooltip','$timeout',function(t,n,a,o,i,r,s){function l(t,n,a){function o(e){var t=6e4*g.minuteStep;return new Date(Math.floor(e.getTime()/t)*t)}function l(e,n){var a=e+n;if(t[0].createTextRange){var o=t[0].createTextRange();o.collapse(!0),o.moveStart('character',e),o.moveEnd('character',a),o.select()}else t[0].setSelectionRange?t[0].setSelectionRange(e,a):angular.isUndefined(t[0].selectionStart)&&(t[0].selectionStart=e,t[0].selectionEnd=a)}function d(){t[0].focus()}var f=r(t,angular.extend({},e,a)),p=a.scope,g=f.$options,m=f.$scope,$=g.lang,h=function(e,t,n){return i.formatDate(e,t,$,n)},v=0,w=g.roundDisplay?o(new Date):new Date,y=n.$dateValue||w,b={hour:y.getHours(),meridian:y.getHours()<12,minute:y.getMinutes(),second:y.getSeconds(),millisecond:y.getMilliseconds()},D=i.getDatetimeFormat(g.timeFormat,$),k=i.hoursFormat(D),S=i.timeSeparator(D),x=i.minutesFormat(D),T=i.secondsFormat(D),C=i.showSeconds(D),M=i.showAM(D);m.$iconUp=g.iconUp,m.$iconDown=g.iconDown,m.$select=function(e,t){f.select(e,t)},m.$moveIndex=function(e,t){f.$moveIndex(e,t)},m.$switchMeridian=function(e){f.switchMeridian(e)},f.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())?(f.$date=e,angular.extend(b,{hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}),f.$build()):f.$isBuilt||f.$build()},f.select=function(e,t,a){(!n.$dateValue||isNaN(n.$dateValue.getTime()))&&(n.$dateValue=new Date(1970,0,1)),angular.isDate(e)||(e=new Date(e)),0===t?n.$dateValue.setHours(e.getHours()):1===t?n.$dateValue.setMinutes(e.getMinutes()):2===t&&n.$dateValue.setSeconds(e.getSeconds()),n.$setViewValue(angular.copy(n.$dateValue)),n.$render(),g.autoclose&&!a&&s(function(){f.hide(!0)})},f.switchMeridian=function(e){if(n.$dateValue&&!isNaN(n.$dateValue.getTime())){var t=(e||n.$dateValue).getHours();n.$dateValue.setHours(12>t?t+12:t-12),n.$setViewValue(angular.copy(n.$dateValue)),n.$render()}},f.$build=function(){var e,t,n=m.midIndex=parseInt(g.length/2,10),a=[];for(e=0;e<g.length;e++)t=new Date(1970,0,1,b.hour-(n-e)*g.hourStep),a.push({date:t,label:h(t,k),selected:f.$date&&f.$isSelected(t,0),disabled:f.$isDisabled(t,0)});var o,i=[];for(e=0;e<g.length;e++)o=new Date(1970,0,1,0,b.minute-(n-e)*g.minuteStep),i.push({date:o,label:h(o,x),selected:f.$date&&f.$isSelected(o,1),disabled:f.$isDisabled(o,1)});var r,s=[];for(e=0;e<g.length;e++)r=new Date(1970,0,1,0,0,b.second-(n-e)*g.secondStep),s.push({date:r,label:h(r,T),selected:f.$date&&f.$isSelected(r,2),disabled:f.$isDisabled(r,2)});var l=[];for(e=0;e<g.length;e++)l.push(C?[a[e],i[e],s[e]]:[a[e],i[e]]);m.rows=l,m.showSeconds=C,m.showAM=M,m.isAM=(f.$date||a[n].date).getHours()<12,m.timeSeparator=S,f.$isBuilt=!0},f.$isSelected=function(e,t){return f.$date?0===t?e.getHours()===f.$date.getHours():1===t?e.getMinutes()===f.$date.getMinutes():2===t?e.getSeconds()===f.$date.getSeconds():void 0:!1},f.$isDisabled=function(e,t){var n;return 0===t?n=e.getTime()+6e4*b.minute+1e3*b.second:1===t?n=e.getTime()+36e5*b.hour+1e3*b.second:2===t&&(n=e.getTime()+36e5*b.hour+6e4*b.minute),n<1*g.minTime||n>1*g.maxTime},m.$arrowAction=function(e,t){'picker'===g.arrowBehavior?f.$setTimeByStep(e,t):f.$moveIndex(e,t)},f.$setTimeByStep=function(e,t){{var n=new Date(f.$date),a=n.getHours(),o=(h(n,k).length,n.getMinutes()),i=(h(n,x).length,n.getSeconds());h(n,T).length}0===t?n.setHours(a-parseInt(g.hourStep,10)*e):1===t?n.setMinutes(o-parseInt(g.minuteStep,10)*e):2===t&&n.setSeconds(i-parseInt(g.secondStep,10)*e),f.select(n,t,!0)},f.$moveIndex=function(e,t){var n;0===t?(n=new Date(1970,0,1,b.hour+e*g.length,b.minute,b.second),angular.extend(b,{hour:n.getHours()})):1===t?(n=new Date(1970,0,1,b.hour,b.minute+e*g.length*g.minuteStep,b.second),angular.extend(b,{minute:n.getMinutes()})):2===t&&(n=new Date(1970,0,1,b.hour,b.minute,b.second+e*g.length*g.secondStep),angular.extend(b,{second:n.getSeconds()})),f.$build()},f.$onMouseDown=function(e){if('input'!==e.target.nodeName.toLowerCase()&&e.preventDefault(),e.stopPropagation(),c){var t=angular.element(e.target);'button'!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler('click')}},f.$onKeyDown=function(e){if(/(38|37|39|40|13)/.test(e.keyCode)&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),e.stopPropagation(),13===e.keyCode)return f.hide(!0);var t=new Date(f.$date),n=t.getHours(),a=h(t,k).length,o=t.getMinutes(),i=h(t,x).length,r=t.getSeconds(),s=h(t,T).length,u=1,c=/(37|39)/.test(e.keyCode),d=2+1*C+1*M;c&&(37===e.keyCode?v=1>v?d-1:v-1:39===e.keyCode&&(v=d-1>v?v+1:0));var m=[0,a],$=0;38===e.keyCode&&($=-1),40===e.keyCode&&($=1);var w=2===v&&C,y=2===v&&!C||3===v&&C;0===v?(t.setHours(n+$*parseInt(g.hourStep,10)),a=h(t,k).length,m=[0,a]):1===v?(t.setMinutes(o+$*parseInt(g.minuteStep,10)),i=h(t,x).length,m=[a+u,i]):w?(t.setSeconds(r+$*parseInt(g.secondStep,10)),s=h(t,T).length,m=[a+u+i+u,s]):y&&(c||f.switchMeridian(),m=[a+u+i+u+(s+u)*C,2]),f.select(t,v,!0),l(m[0],m[1]),p.$digest()}};var E=f.init;f.init=function(){return u&&g.useNative?(t.prop('type','time'),void t.css('-webkit-appearance','textfield')):(c&&(t.prop('type','text'),t.attr('readonly','true'),t.on('click',d)),void E())};var A=f.destroy;f.destroy=function(){u&&g.useNative&&t.off('click',d),A()};var F=f.show;f.show=function(){F(),s(function(){f.$element&&f.$element.on(c?'touchstart':'mousedown',f.$onMouseDown),g.keyboard&&t&&t.on('keydown',f.$onKeyDown)},0,!1)};var V=f.hide;return f.hide=function(e){f.$isShown&&(f.$element&&f.$element.off(c?'touchstart':'mousedown',f.$onMouseDown),g.keyboard&&t&&t.off('keydown',f.$onKeyDown),V(e))},f}var u=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),c='createTouch'in t.document&&u;return e.lang||(e.lang=i.getDefaultLocale()),l.defaults=e,l}]}).directive('bsTimepicker',['$window','$parse','$q','$dateFormatter','$dateParser','$timepicker',function(e,t,n,a,o,i){{var r=i.defaults,s=/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent);e.requestAnimationFrame||e.setTimeout}return{restrict:'EAC',require:'ngModel',link:function(e,t,n,l){function u(e){if(angular.isDate(e)){var t=isNaN(d.minTime)||new Date(e.getTime()).setFullYear(1970,0,1)>=d.minTime,n=isNaN(d.maxTime)||new Date(e.getTime()).setFullYear(1970,0,1)<=d.maxTime,a=t&&n;l.$setValidity('date',a),l.$setValidity('min',t),l.$setValidity('max',n),a&&(l.$dateValue=e)}}function c(){return!l.$dateValue||isNaN(l.$dateValue.getTime())?'':m(l.$dateValue,d.timeFormat)}var d={scope:e,controller:l};angular.forEach(['placement','container','delay','trigger','keyboard','html','animation','template','autoclose','timeType','timeFormat','timezone','modelTimeFormat','useNative','hourStep','minuteStep','secondStep','length','arrowBehavior','iconUp','iconDown','roundDisplay','id','prefixClass','prefixEvent'],function(e){angular.isDefined(n[e])&&(d[e]=n[e])});var f=/^(false|0|)$/i;angular.forEach(['html','container','autoclose','useNative','roundDisplay'],function(e){angular.isDefined(n[e])&&f.test(n[e])&&(d[e]=!1)}),n.bsShow&&e.$watch(n.bsShow,function(e,t){p&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(timepicker),?/i)),e===!0?p.show():p.hide())}),s&&(d.useNative||r.useNative)&&(d.timeFormat='HH:mm');var p=i(t,l,d);d=p.$options;var g=d.lang,m=function(e,t,n){return a.formatDate(e,t,g,n)},$=o({format:d.timeFormat,lang:g});angular.forEach(['minTime','maxTime'],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){p.$options[e]=$.getTimeForAttribute(e,t),!isNaN(p.$options[e])&&p.$build(),u(l.$dateValue)})}),e.$watch(n.ngModel,function(e,t){p.update(l.$dateValue)},!0),l.$parsers.unshift(function(e){var t;if(!e)return l.$setValidity('date',!0),null;var n=angular.isDate(e)?e:$.parse(e,l.$dateValue);return!n||isNaN(n.getTime())?void l.$setValidity('date',!1):(u(n),'string'===d.timeType?(t=$.timezoneOffsetAdjust(n,d.timezone,!0),m(t,d.modelTimeFormat||d.timeFormat)):(t=$.timezoneOffsetAdjust(l.$dateValue,d.timezone,!0),'number'===d.timeType?t.getTime():'unix'===d.timeType?t.getTime()/1e3:'iso'===d.timeType?t.toISOString():new Date(t)))}),l.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:'string'===d.timeType?$.parse(e,null,d.modelTimeFormat):new Date('unix'===d.timeType?1e3*e:e),l.$dateValue=$.timezoneOffsetAdjust(t,d.timezone),c()}),l.$render=function(){t.val(c())},e.$on('$destroy',function(){p&&p.destroy(),d=null,p=null})}}}]),angular.module('mgcrea.ngStrap.tooltip',['mgcrea.ngStrap.helpers.dimensions']).provider('$tooltip',function(){var e=this.defaults={animation:'am-fade',customClass:'',prefixClass:'tooltip',prefixEvent:'tooltip',container:!1,target:!1,placement:'top',template:'tooltip/tooltip.tpl.html',contentTemplate:!1,trigger:'hover focus',keyboard:!1,html:!1,show:!1,title:'',type:'',delay:0,autoClose:!1,bsEnabled:!0,viewport:{selector:'body',padding:0}};this.$get=['$window','$rootScope','$compile','$q','$templateCache','$http','$animate','$sce','dimensions','$$rAF','$timeout',function(n,a,o,i,r,s,l,u,c,d,f){function p(i,r){function s(){N.$emit(H.prefixEvent+'.show',I)}function p(){if(N.$emit(H.prefixEvent+'.hide',I),z===B){if(W&&'focus'===H.trigger)return i[0].blur();O()}}function b(){var e=H.trigger.split(' ');angular.forEach(e,function(e){'click'===e?i.on('click',I.toggle):'manual'!==e&&(i.on('hover'===e?'mouseenter':'focus',I.enter),i.on('hover'===e?'mouseleave':'blur',I.leave),'button'===P&&'hover'!==e&&i.on(v?'touchstart':'mousedown',I.$onFocusElementMouseDown))})}function D(){for(var e=H.trigger.split(' '),t=e.length;t--;){var n=e[t];'click'===n?i.off('click',I.toggle):'manual'!==n&&(i.off('hover'===n?'mouseenter':'focus',I.enter),i.off('hover'===n?'mouseleave':'blur',I.leave),'button'===P&&'hover'!==n&&i.off(v?'touchstart':'mousedown',I.$onFocusElementMouseDown))}}function k(){'focus'!==H.trigger?z.on('keyup',I.$onKeyUp):i.on('keyup',I.$onFocusKeyUp)}function S(){'focus'!==H.trigger?z.off('keyup',I.$onKeyUp):i.off('keyup',I.$onFocusKeyUp)}function x(){f(function(){z.on('click',C),y.on('click',I.hide),_=!0},0,!1)}function T(){_&&(z.off('click',C),y.off('click',I.hide),_=!1)}function C(e){e.stopPropagation()}function M(e){e=e||H.target||i;var a=e[0],o='BODY'===a.tagName,r=a.getBoundingClientRect(),s={};for(var l in r)s[l]=r[l];null===s.width&&(s=angular.extend({},s,{width:r.right-r.left,height:r.bottom-r.top}));var u=o?{top:0,left:0}:c.offset(a),d={scroll:o?t.documentElement.scrollTop||t.body.scrollTop:e.prop('scrollTop')||0},f=o?{width:t.documentElement.clientWidth,height:n.innerHeight}:null;return angular.extend({},s,d,f,u)}function E(e,t,n,a){var o,i=e.split('-');switch(i[0]){case'right':o={top:t.top+t.height/2-a/2,left:t.left+t.width
10
+ };break;case'bottom':o={top:t.top+t.height,left:t.left+t.width/2-n/2};break;case'left':o={top:t.top+t.height/2-a/2,left:t.left-n};break;default:o={top:t.top-a,left:t.left+t.width/2-n/2}}if(!i[1])return o;if('top'===i[0]||'bottom'===i[0])switch(i[1]){case'left':o.left=t.left;break;case'right':o.left=t.left+t.width-n}else if('left'===i[0]||'right'===i[0])switch(i[1]){case'top':o.top=t.top-a;break;case'bottom':o.top=t.top+t.height}return o}function A(e,t){var n=z[0],a=n.offsetWidth,o=n.offsetHeight,i=parseInt(c.css(n,'margin-top'),10),r=parseInt(c.css(n,'margin-left'),10);isNaN(i)&&(i=0),isNaN(r)&&(r=0),e.top=e.top+i,e.left=e.left+r,c.setOffset(n,angular.extend({using:function(e){z.css({top:Math.round(e.top)+'px',left:Math.round(e.left)+'px',right:''})}},e),0);var s=n.offsetWidth,l=n.offsetHeight;if('top'===t&&l!==o&&(e.top=e.top+o-l),!/top-left|top-right|bottom-left|bottom-right/.test(t)){var u=F(t,e,s,l);if(u.left?e.left+=u.left:e.top+=u.top,c.setOffset(n,e),/top|right|bottom|left/.test(t)){var d=/top|bottom/.test(t),f=d?2*u.left-a+s:2*u.top-o+l,p=d?'offsetWidth':'offsetHeight';V(f,n[p],d)}}}function F(e,t,n,a){var o={top:0,left:0},i=H.viewport&&m(H.viewport.selector||H.viewport);if(!i)return o;var r=H.viewport&&H.viewport.padding||0,s=M(i);if(/right|left/.test(e)){var l=t.top-r-s.scroll,u=t.top+r-s.scroll+a;l<s.top?o.top=s.top-l:u>s.top+s.height&&(o.top=s.top+s.height-u)}else{var c=t.left-r,d=t.left+r+n;c<s.left?o.left=s.left-c:d>s.width&&(o.left=s.left+s.width-d)}return o}function V(e,t,n){var a=m('.tooltip-arrow, .arrow',z[0]);a.css(n?'left':'top',50*(1-e/t)+'%').css(n?'top':'left','')}function O(){clearTimeout(R),I.$isShown&&null!==z&&(H.autoClose&&T(),H.keyboard&&S()),j&&(j.$destroy(),j=null),z&&(z.remove(),z=I.$element=null)}var I={},P=i[0].nodeName.toLowerCase(),H=I.$options=angular.extend({},e,r);I.$promise=$(H.template);var N=I.$scope=H.scope&&H.scope.$new()||a.$new();if(H.delay&&angular.isString(H.delay)){var L=H.delay.split(',').map(parseFloat);H.delay=L.length>1?{show:L[0],hide:L[1]}:L[0]}I.$id=H.id||i.attr('id')||'',H.title&&(N.title=u.trustAsHtml(H.title)),N.$setEnabled=function(e){N.$$postDigest(function(){I.setEnabled(e)})},N.$hide=function(){N.$$postDigest(function(){I.hide()})},N.$show=function(){N.$$postDigest(function(){I.show()})},N.$toggle=function(){N.$$postDigest(function(){I.toggle()})},I.$isShown=N.$isShown=!1;var R,Y;H.contentTemplate&&(I.$promise=I.$promise.then(function(e){var t=angular.element(e);return $(H.contentTemplate).then(function(e){var n=m('[ng-bind="content"]',t[0]);return n.length||(n=m('[ng-bind="title"]',t[0])),n.removeAttr('ng-bind').html(e),t[0].outerHTML})}));var q,z,K,U,j;I.$promise.then(function(e){angular.isObject(e)&&(e=e.data),H.html&&(e=e.replace(w,'ng-bind-html="')),e=h.apply(e),K=e,q=o(e),I.init()}),I.init=function(){H.delay&&angular.isNumber(H.delay)&&(H.delay={show:H.delay,hide:H.delay}),'self'===H.container?U=i:angular.isElement(H.container)?U=H.container:H.container&&(U=m(H.container)),b(),H.target&&(H.target=angular.isElement(H.target)?H.target:m(H.target)),H.show&&N.$$postDigest(function(){'focus'===H.trigger?i[0].focus():I.show()})},I.destroy=function(){D(),O(),N.$destroy()},I.enter=function(){return clearTimeout(R),Y='in',H.delay&&H.delay.show?void(R=setTimeout(function(){'in'===Y&&I.show()},H.delay.show)):I.show()},I.show=function(){if(H.bsEnabled&&!I.$isShown){N.$emit(H.prefixEvent+'.show.before',I);var e,t;H.container?(e=U,t=U[0].lastChild?angular.element(U[0].lastChild):null):(e=null,t=i),z&&O(),j=I.$scope.$new(),z=I.$element=q(j,function(e,t){}),z.css({top:'-9999px',left:'-9999px',right:'auto',display:'block',visibility:'hidden'}),H.animation&&z.addClass(H.animation),H.type&&z.addClass(H.prefixClass+'-'+H.type),H.customClass&&z.addClass(H.customClass),t?t.after(z):e.prepend(z),I.$isShown=N.$isShown=!0,g(N),I.$applyPlacement(),angular.version.minor<=2?l.enter(z,e,t,s):l.enter(z,e,t).then(s),g(N),d(function(){z&&z.css({visibility:'visible'})}),H.keyboard&&('focus'!==H.trigger&&I.focus(),k()),H.autoClose&&x()}},I.leave=function(){return clearTimeout(R),Y='out',H.delay&&H.delay.hide?void(R=setTimeout(function(){'out'===Y&&I.hide()},H.delay.hide)):I.hide()};var W,B;I.hide=function(e){I.$isShown&&(N.$emit(H.prefixEvent+'.hide.before',I),W=e,B=z,angular.version.minor<=2?l.leave(z,p):l.leave(z).then(p),I.$isShown=N.$isShown=!1,g(N),H.keyboard&&null!==z&&S(),H.autoClose&&null!==z&&T())},I.toggle=function(){I.$isShown?I.leave():I.enter()},I.focus=function(){z[0].focus()},I.setEnabled=function(e){H.bsEnabled=e},I.setViewport=function(e){H.viewport=e},I.$applyPlacement=function(){if(z){var t=H.placement,n=/\s?auto?\s?/i,a=n.test(t);a&&(t=t.replace(n,'')||e.placement),z.addClass(H.placement);var o=M(),r=z.prop('offsetWidth'),s=z.prop('offsetHeight');if(a){var l=t,u=H.container?m(H.container):i.parent(),c=M(u);l.indexOf('bottom')>=0&&o.bottom+s>c.bottom?t=l.replace('bottom','top'):l.indexOf('top')>=0&&o.top-s<c.top&&(t=l.replace('top','bottom')),('right'===l||'bottom-left'===l||'top-left'===l)&&o.right+r>c.width?t='right'===l?'left':t.replace('left','right'):('left'===l||'bottom-right'===l||'top-right'===l)&&o.left-r<c.left&&(t='left'===l?'right':t.replace('right','left')),z.removeClass(l).addClass(t)}var d=E(t,o,r,s);A(d,t)}},I.$onKeyUp=function(e){27===e.which&&I.$isShown&&(I.hide(),e.stopPropagation())},I.$onFocusKeyUp=function(e){27===e.which&&(i[0].blur(),e.stopPropagation())},I.$onFocusElementMouseDown=function(e){e.preventDefault(),e.stopPropagation(),I.$isShown?i[0].blur():i[0].focus()};var _=!1;return I}function g(e){e.$$phase||e.$root&&e.$root.$$phase||e.$digest()}function m(e,n){return angular.element((n||t).querySelectorAll(e))}function $(e){return b[e]?b[e]:b[e]=s.get(e,{cache:r}).then(function(e){return e.data})}var h=String.prototype.trim,v='createTouch'in n.document,w=/ng-bind="/gi,y=angular.element(n.document),b={};return p}]}).directive('bsTooltip',['$window','$location','$sce','$tooltip','$$rAF',function(e,t,n,a,o){return{restrict:'EAC',scope:!0,link:function(e,t,i,r){var s={scope:e};angular.forEach(['template','contentTemplate','placement','container','delay','trigger','html','animation','backdropAnimation','type','customClass','id'],function(e){angular.isDefined(i[e])&&(s[e]=i[e])});var l=/^(false|0|)$/i;angular.forEach(['html','container'],function(e){angular.isDefined(i[e])&&l.test(i[e])&&(s[e]=!1)});var u=t.attr('data-target');angular.isDefined(u)&&(s.target=l.test(u)?!1:u),e.hasOwnProperty('title')||(e.title=''),i.$observe('title',function(t){if(angular.isDefined(t)||!e.hasOwnProperty('title')){var a=e.title;e.title=n.trustAsHtml(t),angular.isDefined(a)&&o(function(){c&&c.$applyPlacement()})}}),i.bsTooltip&&e.$watch(i.bsTooltip,function(t,n){angular.isObject(t)?angular.extend(e,t):e.title=t,angular.isDefined(n)&&o(function(){c&&c.$applyPlacement()})},!0),i.bsShow&&e.$watch(i.bsShow,function(e,t){c&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(tooltip),?/i)),e===!0?c.show():c.hide())}),i.bsEnabled&&e.$watch(i.bsEnabled,function(e,t){c&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|1|,?(tooltip),?/i)),c.setEnabled(e===!1?!1:!0))}),i.viewport&&e.$watch(i.viewport,function(e){c&&angular.isDefined(e)&&c.setViewport(e)});var c=a(t,s);e.$on('$destroy',function(){c&&c.destroy(),s=null,c=null})}}}]),angular.module('mgcrea.ngStrap.typeahead',['mgcrea.ngStrap.tooltip','mgcrea.ngStrap.helpers.parseOptions']).provider('$typeahead',function(){var e=this.defaults={animation:'am-fade',prefixClass:'typeahead',prefixEvent:'$typeahead',placement:'bottom-left',template:'typeahead/typeahead.tpl.html',trigger:'focus',container:!1,keyboard:!0,html:!1,delay:0,minLength:1,filter:'filter',limit:6,autoSelect:!1,comparator:'',trimValue:!0};this.$get=['$window','$rootScope','$tooltip','$timeout',function(t,n,a,o){function i(t,n,i){var r={},s=angular.extend({},e,i);r=a(t,s);var l=i.scope,u=r.$scope;u.$resetMatches=function(){u.$matches=[],u.$activeIndex=s.autoSelect?0:-1},u.$resetMatches(),u.$activate=function(e){u.$$postDigest(function(){r.activate(e)})},u.$select=function(e,t){u.$$postDigest(function(){r.select(e)})},u.$isVisible=function(){return r.$isVisible()},r.update=function(e){u.$matches=e,u.$activeIndex>=e.length&&(u.$activeIndex=s.autoSelect?0:-1),/^(bottom|bottom-left|bottom-right)$/.test(s.placement)||o(r.$applyPlacement)},r.activate=function(e){u.$activeIndex=e},r.select=function(e){if(-1!==e){var t=u.$matches[e].value;n.$setViewValue(t),n.$render(),u.$resetMatches(),l&&l.$digest(),u.$emit(s.prefixEvent+'.select',t,e,r)}},r.$isVisible=function(){return s.minLength&&n?u.$matches.length&&angular.isString(n.$viewValue)&&n.$viewValue.length>=s.minLength:!!u.$matches.length},r.$getIndex=function(e){var t=u.$matches.length,n=t;if(t){for(n=t;n--&&u.$matches[n].value!==e;);if(!(0>n))return n}},r.$onMouseDown=function(e){e.preventDefault(),e.stopPropagation()},r.$onKeyDown=function(e){/(38|40|13)/.test(e.keyCode)&&(!r.$isVisible()||13===e.keyCode&&-1===u.$activeIndex||(e.preventDefault(),e.stopPropagation()),13===e.keyCode&&u.$matches.length?r.select(u.$activeIndex):38===e.keyCode&&u.$activeIndex>0?u.$activeIndex--:40===e.keyCode&&u.$activeIndex<u.$matches.length-1?u.$activeIndex++:angular.isUndefined(u.$activeIndex)&&(u.$activeIndex=0),u.$digest())};var c=r.show;r.show=function(){c(),o(function(){r.$element&&r.$element.on('mousedown',r.$onMouseDown),s.keyboard&&t&&t.on('keydown',r.$onKeyDown)},0,!1)};var d=r.hide;return r.hide=function(){r.$element&&r.$element.off('mousedown',r.$onMouseDown),s.keyboard&&t&&t.off('keydown',r.$onKeyDown),s.autoSelect||r.activate(-1),d()},r}angular.element(t.document.body);return i.defaults=e,i}]}).directive('bsTypeahead',['$window','$parse','$q','$typeahead','$parseOptions',function(e,t,n,a,o){var i=a.defaults;return{restrict:'EAC',require:'ngModel',link:function(e,t,n,r){var s={scope:e};angular.forEach(['placement','container','delay','trigger','keyboard','html','animation','template','filter','limit','minLength','watchOptions','selectMode','autoSelect','comparator','id','prefixEvent','prefixClass'],function(e){angular.isDefined(n[e])&&(s[e]=n[e])});var l=/^(false|0|)$/i;angular.forEach(['html','container','trimValue'],function(e){angular.isDefined(n[e])&&l.test(n[e])&&(s[e]=!1)}),t.attr('autocomplete','off');var u=s.filter||i.filter,c=s.limit||i.limit,d=s.comparator||i.comparator,f=n.bsOptions;u&&(f+=' | '+u+':$viewValue'),d&&(f+=':'+d),c&&(f+=' | limitTo:'+c);var p=o(f),g=a(t,r,s);if(s.watchOptions){var m=p.$match[7].replace(/\|.+/,'').replace(/\(.*\)/g,'').trim();e.$watchCollection(m,function(t,n){p.valuesFn(e,r).then(function(e){g.update(e),r.$render()})})}e.$watch(n.ngModel,function(t,n){e.$modelValue=t,p.valuesFn(e,r).then(function(e){if(s.selectMode&&!e.length&&t.length>0)return void r.$setViewValue(r.$viewValue.substring(0,r.$viewValue.length-1));e.length>c&&(e=e.slice(0,c));var n=g.$isVisible();n&&g.update(e),(1!==e.length||e[0].value!==t)&&(!n&&g.update(e),r.$render())})}),r.$formatters.push(function(e){var t=p.displayValue(e);return t?t:e&&'object'!=typeof e?e:''}),r.$render=function(){if(r.$isEmpty(r.$viewValue))return t.val('');var e=g.$getIndex(r.$modelValue),n=angular.isDefined(e)?g.$scope.$matches[e].label:r.$viewValue;n=angular.isObject(n)?p.displayValue(n):n;var a=n?n.toString().replace(/<(?:.|\n)*?>/gm,''):'';t.val(s.trimValue===!1?a:a.trim())},e.$on('$destroy',function(){g&&g.destroy(),s=null,g=null})}}}])}(window,document);
11
11
  //# sourceMappingURL=angular-strap.min.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["angular-strap.js","affix/affix.js","button/button.js","alert/alert.js","aside/aside.js","collapse/collapse.js","datepicker/datepicker.js","dropdown/dropdown.js","helpers/date-formatter.js","helpers/date-parser.js","helpers/debounce.js","helpers/dimensions.js","helpers/parse-options.js","helpers/raf.js","modal/modal.js","navbar/navbar.js","popover/popover.js","scrollspy/scrollspy.js","select/select.js","tab/tab.js","timepicker/timepicker.js","tooltip/tooltip.js","typeahead/typeahead.js"],"names":["window","document","undefined","angular","bodyEl","$window","body","windowEl","defaults","AffixFactory","offsetTop","$affix","inlineStyles","options","this","$get","reset","setWidth","initialAffixTop","offsetParent","match","getRequiredAffixClass","unpin","position","top","scrollTop","getScrollTop","scrollHeight","getScrollHeight","targetEl","pageYOffset","directive","parent","target","initialOffsetTop","offsetBottom","affixed","element","init","i","$parseOffsets","on","checkPosition","require","checkPositionWithEventLoop","dimensions","offset","destroy","style","width","off","affix","setTimeout","elementHeight","height","css","addClass","offsetUnpin","offsetHeight","offsetWidth","$debouncedOnResize","$onResize","initialPosition","restrict","affixTarget","$element","forEach","link","key","scope","option","$on","attr","test","controller","activeClass","toggleEvent","compile","children","querySelectorAll","childEl","ngModel","removeAttr","child","$button","constantValueRegExp","isInput","trueValue","falseValue","isDefined","hasExoticValues","viewValue","$formatters","push","$render","modelValue","isActive","equals","checked","activeElement","bind","$modelValue","$$rAF","$setViewValue","toggleClass","$apply","hasClass","$observe","value","nodeName","module","container","provider","backdrop","keyboard","show","duration","type","dismissable","AlertFactory","$alert","$scope","config","extend","$timeout","hide","falseValueRegExp","hasOwnProperty","title","newValue","oldValue","trustAsHtml","bsAlert","content","alert","trigger","toggle","animation","contentTemplate","html","AsideFactory","$aside","requestAnimationFrame","$modal","bsAside","$watch","aside","self","startCollapsed","allowMultiple","$attrs","activeIndexes","$targets","$active","length","index","indexOf","activeItems","splice","activateItem","$options","$collapse","copy","$toggles","$unregisterToggle","$registerToggle","$unregisterTarget","deactivateItem","$viewChangeListeners","fn","fixActiveItemIndexes","$setActive","disallowToggle","$activeIndexes","bsCollapseCtrl","controllers","$animate","ngModelCtrl","attrs","isArray","bsCollapseToggle","$registerTarget","render","active","action","prefixClass","delay","useNative","dateType","dateFormat","timezone","modelDateFormat","dayFormat","monthFormat","yearFormat","monthTitleFormat","yearTitleFormat","strictFormat","autoclose","minDate","Infinity","maxDate","startView","minView","startWeek","daysOfWeekDisabled","iconLeft","iconRight","isNative","DatepickerFactory","parentScope","$datepicker","pickerViews","views","el","selected","date","focus","viewDate","$iconLeft","$iconRight","$picker","$views","$mode","datepickerViews","$selectPane","$toggleMode","setMode","select","isDate","$build","updateDisabledDates","disabledDateRanges","dateRanges","$date","$dateValue","keep","Date","year","getFullYear","month","getDate","mode","pristine","call","$updateSelected","rows","built","$isSelected","$setDisabledEl","disabled","isDisabled","steps","targetDate","getUTCFullYear","getUTCMonth","UTC","$onMouseDown","evt","preventDefault","stopPropagation","isTouch","getUTCDate","$onKeyDown","keyCode","shiftKey","altKey","updateSelected","onKeyDown","$digest","prop","focusElement","_init","_destroy","_show","_hide","blur","previousValue","normalizeDateRanges","ranges","disabledRanges","datepicker","isMaxValid","isValid","isMinValid","isNaN","parsedDate","getTime","$parsers","unshift","$setValidity","getDateFormattedString","formatDate","bsShow","lang","format","$dateFormatter","dateParser","$dateParser","strict","validateAgainstMinMaxDate","getDateForAttribute","disabledDates","parse","timezoneOffsetAdjust","isUndefined","NaN","daySplit","arr","mod","n","m","arrays","size","$sce","weekDaysMin","weekdaysShort","weekDaysLabelsHtml","startDate","picker","weekDaysLabels","slice","concat","split","getMonth","update","firstDayOfMonth","firstDate","getDay","today","firstDateOffset","build","day","days","isToday","toDateString","label","muted","showLabels","labels","time","isSelected","newDate","name","firstMonth","months","lastDate","actualMonth","parseInt","firstYear","years","actualYear","setYear","placement","matchesSelector","DropdownFactory","$dropdown","onBodyClick","items","$rootScope","$new","parentEl","$isShown","removeClass","prototype","transclusion","bsDropdown","dropdown","isString","getDefaultLocale","id","splitTimeFormat","timeFormat","exec","DATETIME_FORMATS","$locale","getDatetimeFormat","SHORTDAY","hoursFormat","minutesFormat","secondsFormat","timeSeparator","showSeconds","dateFilter","ParseDate","seconds","$localeProvider","milliseconds","hours","array","isNumeric","parseFloat","isFinite","indexOfCaseInsensitive","len","str","toString","toLowerCase","DateParserFactory","minutes","getHours","getMilliseconds","getMinutes","proto","noop","toDate","regExpMap","sss","mm","keys","setFnMap","map","clonedFormat","search","v","sortedMap","regExpForFormat","re","join","text","replace","Object","escapeReservedSymbols","RegExp","regex","HH","H","hh","h","a","EEEE","EEE","dd","d","MMMM","MMM","SHORTMONTH","MM","M","DAY","yyyy","yy","y","MONTH","ss","setSeconds","s","setMinutes","setHours","setDate","setMonth","setFullYear","$format","baseDate","setMap","formatRegex","formatSetMap","setMapForFormat","matches","fromDate","substr","getTimeForAttribute","daylightSavingAdjust","undo","func","timeout","context","factory","immediate","apply","args","cancel","callNow","leading","trailing","wait","currentStyle","getComputedStyle","extra","boxRect","getBoundingClientRect","left","docElement","ownerDocument","curPosition","curLeft","curCSSTop","documentElement","clientTop","pageXOffset","scrollLeft","clientLeft","curCSSLeft","calculatePosition","curTop","curOffset","curElem","props","isFunction","using","offsetParentRect","offsetParentElement","outer","$parseOptions","$values","regexp","$match","displayFn","locals","valueName","valueFn","ParseOptionsFactory","groupByFn","valuesFn","$parse","keyName","cancelAnimationFrame","when","values","parseValues","raf","webkitRequestAnimationFrame","mozRequestAnimationFrame","rafSupported","timer","prefixEvent","template","trim","bodyElement","htmlReplaceRegExp","ModalFactory","enterAnimateCallback","promise","modalElement","leaveAnimateCallback","currentTarget","safeDigest","preventEventDefault","$hide","$$postDigest","$id","$show","$promise","templateEl","fetchTemplate","outerHTML","then","modalLinker","backdropElement","right","z-index","data","$compile","remove","$destroy","after","isElement","$emit","defaultPrevented","clonedElement","display","enter","hideOnBackdropClick","$onKeyUp","leave","which","fetchPromises","cache","$templateCache","res","$http","get","bsModal","modal","routeAttr","$navbar","liElements","li","liElement","pattern","path","autoClose","$popover","PopoverFactory","$tooltip","dataTarget","popover","bsPopover","isObject","$applyPlacement","setViewport","viewport","spies","$document","debounce","throttle","ScrollSpyFactory","scrollEl","isWindowSpy","scrollId","$$count","$scrollspy","unbindViewContentLoaded","unbindIncludeContentLoaded","trackedElements","$trackedElements","sortedElements","activeTarget","debouncedCheckPosition","viewportHeight","throttledCheckPosition","debouncedCheckOffsets","checkOffsets","docEl","$activateElement","source","$getTrackedElement","filter","targetElement","querySelector","trackedElement","b","trackElement","toDelete","untrackElement","activate","scrollspy","multiple","allNoneButtons","sort","caretHtml","placeholder","allText","noneText","maxLength","maxLengthHtml","iconCheckmark","SelectFactory","$select","$activeIndex","$isMultiple","$showAllNoneButtons","$allText","$iconCheckmark","$isActive","$isVisible","$selectNone","$matches","$updateActiveIndex","$getIndex","minLength","$viewValue","l","dataMultiple","inputEl","watchedOptions","$watchCollection","parsedOptions","bsOptions","$isEmpty","navClass","$activeClass","$panes","$activePaneChangeListeners","$push","pane","$navClass","$remove","activeIndex","$pane","$tab","transclude","templateUrl","postLink","bsTabsCtrl","bsActivePane","parsedBsActivePane","assign","timeType","modelTimeFormat","minTime","maxTime","hourStep","minuteStep","secondStep","roundDisplay","iconUp","iconDown","arrowBehavior","timepickerFactory","hour","meridian","coeff","selRange","end","start","setSelectionRange","collapse","selectionStart","moveStart","selectionEnd","moveEnd","$timepicker","floorMinutes","floor","selectedIndex","defaultDate","second","getSeconds","millisecond","$iconUp","$iconDown","$moveIndex","$switchMeridian","switchMeridian","minute","midIndex","$isDisabled","showAM","isAM","selectedTime","$arrowAction","$setTimeByStep","hoursLength","triggerHandler","secondsLength","sepLength","lateralMove","count","minutesLength","selectRange","incr","isSeconds","isMeridian","createSelection","createTextRange","parsedTime","getTimeFormattedString","timepicker","validateAgainstMinMaxTime","bsEnabled","selector","padding","String","$body","_tipToHide","tipElement","triggers","unbindTriggerEvents","bindKeyboardEvents","$onFocusElementMouseDown","unbindKeyboardEvents","_autoCloseEventsBinded","bindAutoCloseEvents","unbindAutoCloseEvents","stopEventPropagation","event","getPosition","rect","elRect","p","scroll","isBody","getCalculatedOffset","actualWidth","actualHeight","outerDims","clientWidth","innerHeight","tip","marginTop","marginLeft","setOffset","delta","getViewportAdjustedDelta","isVertical","replaceArrow","arrowDelta","arrowOffsetPosition","viewportPadding","topEdgeOffset","$viewport","viewportDimensions","leftEdgeOffset","rightEdgeOffset","dimension","isHorizontal","findElement","$arrow","clearTimeout","tipScope","$$phase","$setEnabled","setEnabled","isEnabled","contentEl","tipLinker","tipTemplate","isNumber","tipContainer","bindTriggerEvents","destroyTipElement","hoverState","lastChild","visibility","prepend","_blur","elementPosition","autoPlace","originalPlacement","containerPosition","tipHeight","tipPosition","applyPlacement","tipWidth","TooltipFactory","$location","tooltip","bsTooltip","limit","autoSelect","comparator","trimValue","$typeahead","$resetMatches","TypeaheadFactory","typeahead","watchOptions","selectMode","isVisible","displayValue","val"],"mappings":"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","file":"angular-strap.min.js","sourcesContent":["(function(window, document, undefined) {\n'use strict';\n\n// Source: module.js\nangular.module('mgcrea.ngStrap', [\n 'mgcrea.ngStrap.modal',\n 'mgcrea.ngStrap.aside',\n 'mgcrea.ngStrap.alert',\n 'mgcrea.ngStrap.button',\n 'mgcrea.ngStrap.select',\n 'mgcrea.ngStrap.datepicker',\n 'mgcrea.ngStrap.timepicker',\n 'mgcrea.ngStrap.navbar',\n 'mgcrea.ngStrap.tooltip',\n 'mgcrea.ngStrap.popover',\n 'mgcrea.ngStrap.dropdown',\n 'mgcrea.ngStrap.typeahead',\n 'mgcrea.ngStrap.scrollspy',\n 'mgcrea.ngStrap.affix',\n 'mgcrea.ngStrap.tab',\n 'mgcrea.ngStrap.collapse'\n]);\n\n// Source: affix/affix.js\nangular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mgcrea.ngStrap.helpers.debounce'])\n\n .provider('$affix', function() {\n\n var defaults = this.defaults = {\n offsetTop: 'auto',\n inlineStyles: true\n };\n\n this.$get = function($window, debounce, dimensions) {\n\n var bodyEl = angular.element($window.document.body);\n var windowEl = angular.element($window);\n\n function AffixFactory(element, config) {\n\n var $affix = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var targetEl = options.target;\n\n // Initial private vars\n var reset = 'affix affix-top affix-bottom',\n setWidth = false,\n initialAffixTop = 0,\n initialOffsetTop = 0,\n offsetTop = 0,\n offsetBottom = 0,\n affixed = null,\n unpin = null;\n\n var parent = element.parent();\n // Options: custom parent\n if (options.offsetParent) {\n if (options.offsetParent.match(/^\\d+$/)) {\n for (var i = 0; i < (options.offsetParent * 1) - 1; i++) {\n parent = parent.parent();\n }\n }\n else {\n parent = angular.element(options.offsetParent);\n }\n }\n\n $affix.init = function() {\n\n this.$parseOffsets();\n initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n setWidth = !element[0].style.width;\n\n // Bind events\n targetEl.on('scroll', this.checkPosition);\n targetEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', this.$debouncedOnResize);\n\n // Both of these checkPosition() calls are necessary for the case where\n // the user hits refresh after scrolling to the bottom of the page.\n this.checkPosition();\n this.checkPositionWithEventLoop();\n\n };\n\n $affix.destroy = function() {\n\n // Unbind events\n targetEl.off('scroll', this.checkPosition);\n targetEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', this.$debouncedOnResize);\n\n };\n\n $affix.checkPositionWithEventLoop = function() {\n\n // IE 9 throws an error if we use 'this' instead of '$affix'\n // in this setTimeout call\n setTimeout($affix.checkPosition, 1);\n\n };\n\n $affix.checkPosition = function() {\n // if (!this.$element.is(':visible')) return\n\n var scrollTop = getScrollTop();\n var position = dimensions.offset(element[0]);\n var elementHeight = dimensions.height(element[0]);\n\n // Get required affix class according to position\n var affix = getRequiredAffixClass(unpin, position, elementHeight);\n\n // Did affix status changed this last check?\n if(affixed === affix) return;\n affixed = affix;\n\n // Add proper affix class\n element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\n\n if(affix === 'top') {\n unpin = null;\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', '');\n }\n } else if(affix === 'bottom') {\n if (options.offsetUnpin) {\n unpin = -(options.offsetUnpin * 1);\n }\n else {\n // Calculate unpin threshold when affixed to bottom.\n // Hopefully the browser scrolls pixel by pixel.\n unpin = position.top - scrollTop;\n }\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n }\n } else { // affix === 'middle'\n unpin = null;\n if(setWidth) {\n element.css('width', element[0].offsetWidth + 'px');\n }\n if (options.inlineStyles) {\n element.css('position', 'fixed');\n element.css('top', initialAffixTop + 'px');\n }\n }\n\n };\n\n $affix.$onResize = function() {\n $affix.$parseOffsets();\n $affix.checkPosition();\n };\n $affix.$debouncedOnResize = debounce($affix.$onResize, 50);\n\n $affix.$parseOffsets = function() {\n var initialPosition = element.css('position');\n // Reset position to calculate correct offsetTop\n if (options.inlineStyles){\n element.css('position', (options.offsetParent) ? '' : 'relative');\n }\n\n if(options.offsetTop) {\n if(options.offsetTop === 'auto') {\n options.offsetTop = '+0';\n }\n if(options.offsetTop.match(/^[-+]\\d+$/)) {\n initialAffixTop = - options.offsetTop * 1;\n if(options.offsetParent) {\n offsetTop = dimensions.offset(parent[0]).top + (options.offsetTop * 1);\n }\n else {\n offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\n }\n }\n else {\n offsetTop = options.offsetTop * 1;\n }\n }\n\n if(options.offsetBottom) {\n if(options.offsetParent && options.offsetBottom.match(/^[-+]\\d+$/)) {\n // add 1 pixel due to rounding problems...\n offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + (options.offsetBottom * 1) + 1;\n }\n else {\n offsetBottom = options.offsetBottom * 1;\n }\n }\n\n // Bring back the element's position after calculations\n if (options.inlineStyles){\n element.css('position', initialPosition);\n }\n };\n\n // Private methods\n\n function getRequiredAffixClass(unpin, position, elementHeight) {\n\n var scrollTop = getScrollTop();\n var scrollHeight = getScrollHeight();\n\n if(scrollTop <= offsetTop) {\n return 'top';\n } else if(unpin !== null && (scrollTop + unpin <= position.top)) {\n return 'middle';\n } else if(offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n return 'bottom';\n } else {\n return 'middle';\n }\n\n }\n\n function getScrollTop() {\n return targetEl[0] === $window ? $window.pageYOffset : targetEl[0].scrollTop;\n }\n\n function getScrollHeight() {\n return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight;\n }\n\n $affix.init();\n return $affix;\n\n }\n\n return AffixFactory;\n\n };\n\n })\n\n .directive('bsAffix', function($affix, $window) {\n\n return {\n restrict: 'EAC',\n require: '^?bsAffixTarget',\n link: function postLink(scope, element, attr, affixTarget) {\n\n var options = {scope: scope, target: affixTarget ? affixTarget.$element : angular.element($window)};\n angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin', 'inlineStyles'], function(key) {\n if(angular.isDefined(attr[key])) {\n var option = attr[key];\n if (/true/i.test(option)) option = true;\n if (/false/i.test(option)) option = false;\n options[key] = option;\n }\n });\n\n var affix = $affix(element, options);\n scope.$on('$destroy', function() {\n affix && affix.destroy();\n options = null;\n affix = null;\n });\n\n }\n };\n\n })\n\n .directive('bsAffixTarget', function() {\n return {\n controller: function($element) {\n this.$element = $element;\n }\n };\n });\n\n// Source: button/button.js\nangular.module('mgcrea.ngStrap.button', [])\n\n .provider('$button', function() {\n\n var defaults = this.defaults = {\n activeClass:'active',\n toggleEvent:'click'\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsCheckboxGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"checkbox\"]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.attr('bs-checkbox', '');\n childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));\n });\n }\n\n };\n\n })\n\n .directive('bsCheckbox', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support label > input[type=\"checkbox\"]\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;\n if(constantValueRegExp.test(attr.trueValue)) {\n trueValue = scope.$eval(attr.trueValue);\n }\n var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;\n if(constantValueRegExp.test(attr.falseValue)) {\n falseValue = scope.$eval(attr.falseValue);\n }\n\n // Parse exotic values\n var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';\n if(hasExoticValues) {\n controller.$parsers.push(function(viewValue) {\n // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue);\n return viewValue ? trueValue : falseValue;\n });\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n return angular.equals(modelValue, trueValue);\n });\n // Fix rendering for exotic values\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n controller.$render();\n });\n }\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, trueValue);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n if(!isInput) {\n controller.$setViewValue(!activeElement.hasClass('active'));\n }\n if(!hasExoticValues) {\n controller.$render();\n }\n });\n });\n\n }\n\n };\n\n })\n\n .directive('bsRadioGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"radio\"]');\n angular.forEach(children, function(child) {\n angular.element(child).attr('bs-radio', '');\n angular.element(child).attr('ng-model', attr.ngModel);\n });\n }\n\n };\n\n })\n\n .directive('bsRadio', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support `label > input[type=\"radio\"]` markup\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var value;\n attr.$observe('value', function(v) {\n value = constantValueRegExp.test(v) ? scope.$eval(v) : v;\n controller.$render();\n });\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, value);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n controller.$setViewValue(value);\n controller.$render();\n });\n });\n\n }\n\n };\n\n });\n\n// Source: alert/alert.js\n// @BUG: following snippet won't compile correctly\n// @TODO: submit issue to core\n// '<span ng-if=\"title\"><strong ng-bind=\"title\"></strong>&nbsp;</span><span ng-bind-html=\"content\"></span>' +\n\nangular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal'])\n\n .provider('$alert', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'alert',\n prefixEvent: 'alert',\n placement: null,\n template: 'alert/alert.tpl.html',\n container: false,\n element: null,\n backdrop: false,\n keyboard: true,\n show: true,\n // Specific options\n duration: false,\n type: false,\n dismissable: true\n };\n\n this.$get = function($modal, $timeout) {\n\n function AlertFactory(config) {\n\n var $alert = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $alert = $modal(options);\n\n // Support scope as string options [/*title, content, */ type, dismissable]\n $alert.$scope.dismissable = !!options.dismissable;\n if(options.type) {\n $alert.$scope.type = options.type;\n }\n\n // Support auto-close duration\n var show = $alert.show;\n if(options.duration) {\n $alert.show = function() {\n show();\n $timeout(function() {\n $alert.hide();\n }, options.duration * 1000);\n };\n }\n\n return $alert;\n\n }\n\n return AlertFactory;\n\n };\n\n })\n\n .directive('bsAlert', function($window, $sce, $alert) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'placement', 'keyboard', 'html', 'container', 'animation', 'duration', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['keyboard', 'html', 'container', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content', 'type'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAlert && scope.$watch(attr.bsAlert, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize alert\n var alert = $alert(options);\n\n // Trigger\n element.on(attr.trigger || 'click', alert.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (alert) alert.destroy();\n options = null;\n alert = null;\n });\n\n }\n };\n\n });\n\n// Source: aside/aside.js\nangular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal'])\n\n .provider('$aside', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade-and-slide-right',\n prefixClass: 'aside',\n prefixEvent: 'aside',\n placement: 'right',\n template: 'aside/aside.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($modal) {\n\n function AsideFactory(config) {\n\n var $aside = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $aside = $modal(options);\n\n return $aside;\n\n }\n\n return AsideFactory;\n\n };\n\n })\n\n .directive('bsAside', function($window, $sce, $aside) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAside && scope.$watch(attr.bsAside, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize aside\n var aside = $aside(options);\n\n // Trigger\n element.on(attr.trigger || 'click', aside.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (aside) aside.destroy();\n options = null;\n aside = null;\n });\n\n }\n };\n\n });\n\n// Source: collapse/collapse.js\nangular.module('mgcrea.ngStrap.collapse', [])\n\n .provider('$collapse', function() {\n\n var defaults = this.defaults = {\n animation: 'am-collapse',\n disallowToggle: false,\n activeClass: 'in',\n startCollapsed: false,\n allowMultiple: false\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['disallowToggle', 'startCollapsed', 'allowMultiple'], function(key) {\n if(angular.isDefined($attrs[key]) && falseValueRegExp.test($attrs[key]))\n self.$options[key] = false;\n });\n\n self.$toggles = [];\n self.$targets = [];\n\n self.$viewChangeListeners = [];\n\n self.$registerToggle = function(element) {\n self.$toggles.push(element);\n };\n self.$registerTarget = function(element) {\n self.$targets.push(element);\n };\n\n self.$unregisterToggle = function(element) {\n var index = self.$toggles.indexOf(element);\n // remove toggle from $toggles array\n self.$toggles.splice(index, 1);\n };\n self.$unregisterTarget = function(element) {\n var index = self.$targets.indexOf(element);\n\n // remove element from $targets array\n self.$targets.splice(index, 1);\n\n if (self.$options.allowMultiple) {\n // remove target index from $active array values\n deactivateItem(element);\n }\n\n // fix active item indexes\n fixActiveItemIndexes(index);\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n // use array to store all the currently open panels\n self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n self.$setActive = $scope.$setActive = function(value) {\n if(angular.isArray(value)) {\n self.$targets.$active = value;\n }\n else if(!self.$options.disallowToggle) {\n // toogle element active status\n isActive(value) ? deactivateItem(value) : activateItem(value);\n } else {\n activateItem(value);\n }\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$activeIndexes = function() {\n return self.$options.allowMultiple ? self.$targets.$active :\n self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n };\n\n function fixActiveItemIndexes(index) {\n // item with index was removed, so we\n // need to adjust other items index values\n var activeIndexes = self.$targets.$active;\n for(var i = 0; i < activeIndexes.length; i++) {\n if (index < activeIndexes[i]) {\n activeIndexes[i] = activeIndexes[i] - 1;\n }\n\n // the last item is active, so we need to\n // adjust its index\n if (activeIndexes[i] === self.$targets.length) {\n activeIndexes[i] = self.$targets.length - 1;\n }\n }\n }\n\n function isActive(value) {\n var activeItems = self.$targets.$active;\n return activeItems.indexOf(value) === -1 ? false : true;\n }\n\n function deactivateItem(value) {\n var index = self.$targets.$active.indexOf(value);\n if (index !== -1) {\n self.$targets.$active.splice(index, 1);\n }\n }\n\n function activateItem(value) {\n if (!self.$options.allowMultiple) {\n // remove current selected item\n self.$targets.$active.splice(0, 1);\n }\n\n if (self.$targets.$active.indexOf(value) === -1) {\n self.$targets.$active.push(value);\n }\n }\n\n };\n\n this.$get = function() {\n var $collapse = {};\n $collapse.defaults = defaults;\n $collapse.controller = controller;\n return $collapse;\n };\n\n })\n\n .directive('bsCollapse', function($window, $animate, $collapse) {\n\n var defaults = $collapse.defaults;\n\n return {\n require: ['?ngModel', 'bsCollapse'],\n controller: ['$scope', '$element', '$attrs', $collapse.controller],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n if (angular.isArray(modelValue)) {\n // model value is an array, so just replace\n // the active items directly\n bsCollapseCtrl.$setActive(modelValue);\n }\n else {\n var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n if (angular.isArray(activeIndexes)) {\n // we have an array of selected indexes\n if (activeIndexes.indexOf(modelValue * 1) === -1) {\n // item with modelValue index is not active\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n else if (activeIndexes !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n return modelValue;\n });\n\n }\n\n }\n };\n\n })\n\n .directive('bsCollapseToggle', function() {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base attr\n element.attr('data-toggle', 'collapse');\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerToggle(element);\n\n // remove toggle from collapse controller when toggle is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterToggle(element);\n });\n\n element.on('click', function() {\n var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n bsCollapseCtrl.$setActive(index * 1);\n scope.$apply();\n });\n\n }\n };\n\n })\n\n .directive('bsCollapseTarget', function($animate) {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n // scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base class\n element.addClass('collapse');\n\n // Add animation class\n if(bsCollapseCtrl.$options.animation) {\n element.addClass(bsCollapseCtrl.$options.animation);\n }\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerTarget(element);\n\n // remove pane target from collapse controller when target is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterTarget(element);\n });\n\n function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$activeIndexes();\n var action = 'removeClass';\n if (angular.isArray(active)) {\n if (active.indexOf(index) !== -1) {\n action = 'addClass';\n }\n }\n else if (index === active) {\n action = 'addClass';\n }\n\n $animate[action](element, bsCollapseCtrl.$options.activeClass);\n }\n\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n\n// Source: datepicker/datepicker.js\nangular.module('mgcrea.ngStrap.datepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$datepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'datepicker',\n prefixClass: 'datepicker',\n placement: 'bottom-left',\n template: 'datepicker/datepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: false,\n dateType: 'date',\n dateFormat: 'shortDate',\n timezone: null,\n modelDateFormat: null,\n dayFormat: 'dd',\n monthFormat: 'MMM',\n yearFormat: 'yyyy',\n monthTitleFormat: 'MMMM yyyy',\n yearTitleFormat: 'yyyy',\n strictFormat: false,\n autoclose: false,\n minDate: -Infinity,\n maxDate: +Infinity,\n startView: 0,\n minView: 0,\n startWeek: 0,\n daysOfWeekDisabled: '',\n iconLeft: 'glyphicon glyphicon-chevron-left',\n iconRight: 'glyphicon glyphicon-chevron-right'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function DatepickerFactory(element, controller, config) {\n\n var $datepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $datepicker.$options;\n var scope = $datepicker.$scope;\n if(options.startView) options.startView -= options.minView;\n\n // View vars\n\n var pickerViews = datepickerViews($datepicker);\n $datepicker.$views = pickerViews.views;\n var viewDate = pickerViews.viewDate;\n scope.$mode = options.startView;\n scope.$iconLeft = options.iconLeft;\n scope.$iconRight = options.iconRight;\n var $picker = $datepicker.$views[scope.$mode];\n\n // Scope methods\n\n scope.$select = function(date) {\n $datepicker.select(date);\n };\n scope.$selectPane = function(value) {\n $datepicker.$selectPane(value);\n };\n scope.$toggleMode = function() {\n $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);\n };\n\n // Public methods\n\n $datepicker.update = function(date) {\n // console.warn('$datepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $datepicker.$date = date;\n $picker.update.call($picker, date);\n }\n // Build only if pristine\n $datepicker.$build(true);\n };\n\n $datepicker.updateDisabledDates = function(dateRanges) {\n options.disabledDateRanges = dateRanges;\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);\n }\n };\n\n $datepicker.select = function(date, keep) {\n // console.warn('$datepicker.select', date, scope.$mode);\n if(!angular.isDate(controller.$dateValue)) controller.$dateValue = new Date(date);\n if(!scope.$mode || keep) {\n controller.$setViewValue(angular.copy(date));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $datepicker.hide(true); });\n }\n } else {\n angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});\n $datepicker.setMode(scope.$mode - 1);\n $datepicker.$build();\n }\n };\n\n $datepicker.setMode = function(mode) {\n // console.warn('$datepicker.setMode', mode);\n scope.$mode = mode;\n $picker = $datepicker.$views[scope.$mode];\n $datepicker.$build();\n };\n\n // Protected methods\n\n $datepicker.$build = function(pristine) {\n // console.warn('$datepicker.$build() viewDate=%o', viewDate);\n if(pristine === true && $picker.built) return;\n if(pristine === false && !$picker.built) return;\n $picker.build.call($picker);\n };\n\n $datepicker.$updateSelected = function() {\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], updateSelected);\n }\n };\n\n $datepicker.$isSelected = function(date) {\n return $picker.isSelected(date);\n };\n\n $datepicker.$setDisabledEl = function(el) {\n el.disabled = $picker.isDisabled(el.date);\n };\n\n $datepicker.$selectPane = function(value) {\n var steps = $picker.steps;\n // set targetDate to first day of month to avoid problems with\n // date values rollover. This assumes the viewDate does not\n // depend on the day of the month\n var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));\n angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});\n $datepicker.$build();\n };\n\n $datepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $datepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n if(evt.keyCode === 13) {\n if(!scope.$mode) {\n return $datepicker.hide(true);\n } else {\n return scope.$apply(function() { $datepicker.setMode(scope.$mode - 1); });\n }\n }\n\n // Navigate with keyboard\n $picker.onKeyDown(evt);\n parentScope.$digest();\n };\n\n // Private\n\n function updateSelected(el) {\n el.selected = $datepicker.$isSelected(el.date);\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $datepicker.init;\n $datepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'date');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $datepicker.destroy;\n $datepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $datepicker.show;\n $datepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // if $datepicker is no longer showing, don't setup events\n if(!$datepicker.$isShown) return;\n $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $datepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $datepicker.hide;\n $datepicker.hide = function(blur) {\n if(!$datepicker.$isShown) return;\n $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $datepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $datepicker;\n\n }\n\n DatepickerFactory.defaults = defaults;\n return DatepickerFactory;\n\n };\n\n })\n\n .directive('bsDatepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {\n\n var defaults = $datepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'timezone', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!datepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);\n newValue === true ? datepicker.show() : datepicker.hide();\n });\n\n // Initialize datepicker\n var datepicker = $datepicker(element, controller, options);\n options = datepicker.$options;\n // Set expected iOS format\n if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';\n\n var lang = options.lang;\n\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n // Observe attributes for changes\n angular.forEach(['minDate', 'maxDate'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n // console.warn('attr.$observe(%s)=%o', key, newValue);\n datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);\n // Build only if dirty\n !isNaN(datepicker.$options[key]) && datepicker.$build(false);\n validateAgainstMinMaxDate(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n datepicker.update(controller.$dateValue);\n }, true);\n\n // Normalize undefined/null/empty array,\n // so that we don't treat changing from undefined->null as a change.\n function normalizeDateRanges(ranges) {\n if (!ranges || !ranges.length) return null;\n return ranges;\n }\n\n if (angular.isDefined(attr.disabledDates)) {\n scope.$watch(attr.disabledDates, function(disabledRanges, previousValue) {\n disabledRanges = normalizeDateRanges(disabledRanges);\n previousValue = normalizeDateRanges(previousValue);\n\n if (disabledRanges) {\n datepicker.updateDisabledDates(disabledRanges);\n }\n });\n }\n\n function validateAgainstMinMaxDate(parsedDate) {\n if (!angular.isDate(parsedDate)) return;\n var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;\n var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(isValid) controller.$dateValue = parsedDate;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n controller.$setValidity('date', true);\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n return null;\n }\n var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedDate || isNaN(parsedDate.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxDate(parsedDate);\n }\n\n if(options.dateType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedDate, options.timezone, true);\n return formatDate(date, options.modelDateFormat || options.dateFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.dateType === 'number') {\n return date.getTime();\n } else if(options.dateType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.dateType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.dateType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelDateFormat);\n } else if(options.dateType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) {\n // var today = new Date();\n // date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n // }\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getDateFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getDateFormattedString());\n };\n\n function getDateFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(datepicker) datepicker.destroy();\n options = null;\n datepicker = null;\n });\n\n }\n };\n\n })\n\n .provider('datepickerViews', function() {\n\n var defaults = this.defaults = {\n dayFormat: 'dd',\n daySplit: 7\n };\n\n // Split array into smaller arrays\n function split(arr, size) {\n var arrays = [];\n while(arr.length > 0) {\n arrays.push(arr.splice(0, size));\n }\n return arrays;\n }\n\n // Modulus operator\n function mod(n, m) {\n return ((n % m) + m) % m;\n }\n\n this.$get = function($dateFormatter, $dateParser, $sce) {\n\n return function(picker) {\n\n var scope = picker.$scope;\n var options = picker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n var weekDaysLabelsHtml = $sce.trustAsHtml('<th class=\"dow text-center\">' + weekDaysLabels.join('</th><th class=\"dow text-center\">') + '</th>');\n\n var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n\n var views = [{\n format: options.dayFormat,\n split: 7,\n steps: { month: 1 },\n update: function(date, force) {\n if(!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getDate() !== viewDate.date || date.getDate() === 1) {\n // chaging picker current month will cause viewDate.date to be set to first day of the month,\n // in $datepicker.$selectPane, so picker would not update selected day display if\n // user picks first day of the new month.\n // As a workaround, we are always forcing update when picked date is first day of month.\n viewDate.date = picker.$date.getDate();\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5), firstDateOffset = firstDate.getTimezoneOffset();\n var today = dateParser.timezoneOffsetAdjust(new Date(), options.timezone).toDateString();\n // Handle daylight time switch\n if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);\n var days = [], day;\n for(var i = 0; i < 42; i++) { // < 7 * 6\n day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));\n days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n }\n scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);\n scope.showLabels = true;\n scope.labels = weekDaysLabelsHtml;\n scope.rows = split(days, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();\n },\n isDisabled: function(date) {\n var time = date.getTime();\n\n // Disabled because of min/max date.\n if (time < options.minDate || time > options.maxDate) return true;\n\n // Disabled due to being a disabled day of the week\n if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;\n\n // Disabled because of disabled date range.\n if (options.disabledDateRanges) {\n for (var i = 0; i < options.disabledDateRanges.length; i++) {\n if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {\n return true;\n }\n }\n }\n\n return false;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualTime = picker.$date.getTime();\n var newDate;\n\n if(evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);\n else if(evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);\n else if(evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);\n else if(evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'month',\n format: options.monthFormat,\n split: 4,\n steps: { year: 1 },\n update: function(date, force) {\n if(!this.built || date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstMonth = new Date(viewDate.year, 0, 1);\n var months = [], month;\n for (var i = 0; i < 12; i++) {\n month = new Date(viewDate.year, i, 1);\n months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n }\n scope.title = formatDate(month, options.yearTitleFormat);\n scope.showLabels = false;\n scope.rows = split(months, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualMonth = picker.$date.getMonth();\n var newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setMonth(actualMonth - 1);\n else if(evt.keyCode === 38) newDate.setMonth(actualMonth - 4);\n else if(evt.keyCode === 39) newDate.setMonth(actualMonth + 1);\n else if(evt.keyCode === 40) newDate.setMonth(actualMonth + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'year',\n format: options.yearFormat,\n split: 4,\n steps: { year: 12 },\n update: function(date, force) {\n if(!this.built || force || parseInt(date.getFullYear()/20, 10) !== parseInt(viewDate.year/20, 10)) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstYear = viewDate.year - viewDate.year % (this.split * 3);\n var years = [], year;\n for (var i = 0; i < 12; i++) {\n year = new Date(firstYear + i, 0, 1);\n years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});\n }\n scope.title = years[0].label + '-' + years[years.length - 1].label;\n scope.showLabels = false;\n scope.rows = split(years, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear() + 1, 0, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualYear = picker.$date.getFullYear(),\n newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setYear(actualYear - 1);\n else if(evt.keyCode === 38) newDate.setYear(actualYear - 4);\n else if(evt.keyCode === 39) newDate.setYear(actualYear + 1);\n else if(evt.keyCode === 40) newDate.setYear(actualYear + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }];\n\n return {\n views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,\n viewDate: viewDate\n };\n\n };\n\n };\n\n });\n\n// Source: dropdown/dropdown.js\nangular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$dropdown', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'dropdown',\n prefixEvent: 'dropdown',\n placement: 'bottom-left',\n template: 'dropdown/dropdown.tpl.html',\n trigger: 'click',\n container: false,\n keyboard: true,\n html: false,\n delay: 0\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;\n\n function DropdownFactory(element, config) {\n\n var $dropdown = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n $dropdown = $tooltip(element, options);\n var parentEl = element.parent();\n\n // Protected methods\n\n $dropdown.$onKeyDown = function(evt) {\n if (!/(38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Retrieve focused index\n var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));\n if(!items.length) return;\n var index;\n angular.forEach(items, function(el, i) {\n if(matchesSelector && matchesSelector.call(el, ':focus')) index = i;\n });\n\n // Navigate with keyboard\n if(evt.keyCode === 38 && index > 0) index--;\n else if(evt.keyCode === 40 && index < items.length - 1) index++;\n else if(angular.isUndefined(index)) index = 0;\n items.eq(index)[0].focus();\n\n };\n\n // Overrides\n\n var show = $dropdown.show;\n $dropdown.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n bodyEl.on('click', onBodyClick);\n }, 0, false);\n parentEl.hasClass('dropdown') && parentEl.addClass('open');\n };\n\n var hide = $dropdown.hide;\n $dropdown.hide = function() {\n if(!$dropdown.$isShown) return;\n options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n bodyEl.off('click', onBodyClick);\n parentEl.hasClass('dropdown') && parentEl.removeClass('open');\n hide();\n };\n\n var destroy = $dropdown.destroy;\n $dropdown.destroy = function() {\n bodyEl.off('click', onBodyClick);\n destroy();\n };\n\n // Private functions\n\n function onBodyClick(evt) {\n if(evt.target === element[0]) return;\n return evt.target !== element[0] && $dropdown.hide();\n }\n\n return $dropdown;\n\n }\n\n return DropdownFactory;\n\n };\n\n })\n\n .directive('bsDropdown', function($window, $sce, $dropdown) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as an object\n attr.bsDropdown && scope.$watch(attr.bsDropdown, function(newValue, oldValue) {\n scope.content = newValue;\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!dropdown || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(dropdown),?/i);\n newValue === true ? dropdown.show() : dropdown.hide();\n });\n\n // Initialize dropdown\n var dropdown = $dropdown(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (dropdown) dropdown.destroy();\n options = null;\n dropdown = null;\n });\n\n }\n };\n\n });\n\n// Source: helpers/date-formatter.js\nangular.module('mgcrea.ngStrap.helpers.dateFormatter', [])\n\n .service('$dateFormatter', function($locale, dateFilter) {\n\n // The unused `lang` arguments are on purpose. The default implementation does not\n // use them and it always uses the locale loaded into the `$locale` service.\n // Custom implementations might use it, thus allowing different directives to\n // have different languages.\n\n this.getDefaultLocale = function() {\n return $locale.id;\n };\n\n // Format is either a data format name, e.g. \"shortTime\" or \"fullDate\", or a date format\n // Return either the corresponding date format or the given date format.\n this.getDatetimeFormat = function(format, lang) {\n return $locale.DATETIME_FORMATS[format] || format;\n };\n\n this.weekdaysShort = function(lang) {\n return $locale.DATETIME_FORMATS.SHORTDAY;\n };\n\n function splitTimeFormat(format) {\n return /(h+)([:\\.])?(m+)([:\\.])?(s*)[ ]?(a?)/i.exec(format).slice(1);\n }\n\n // h:mm a => h\n this.hoursFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[0];\n };\n\n // h:mm a => mm\n this.minutesFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[2];\n };\n\n // h:mm:ss a => ss\n this.secondsFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => :\n this.timeSeparator = function(timeFormat) {\n return splitTimeFormat(timeFormat)[1];\n };\n\n // h:mm:ss a => true, h:mm a => false\n this.showSeconds = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => true, H.mm => false\n this.showAM = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[5];\n };\n\n this.formatDate = function(date, format, lang, timezone){\n return dateFilter(date, format, timezone);\n };\n\n });\n\n// Source: helpers/date-parser.js\nangular.module('mgcrea.ngStrap.helpers.dateParser', [])\n\n.provider('$dateParser', function($localeProvider) {\n\n // define a custom ParseDate object to use instead of native Date\n // to avoid date values wrapping when setting date component values\n function ParseDate() {\n this.year = 1970;\n this.month = 0;\n this.day = 1;\n this.hours = 0;\n this.minutes = 0;\n this.seconds = 0;\n this.milliseconds = 0;\n }\n\n ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };\n ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };\n ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };\n ParseDate.prototype.setHours = function(value) { this.hours = value; };\n ParseDate.prototype.getHours = function() { return this.hours; };\n ParseDate.prototype.setDate = function(value) { this.day = value; };\n ParseDate.prototype.setMonth = function(value) { this.month = value; };\n ParseDate.prototype.setFullYear = function(value) { this.year = value; };\n ParseDate.prototype.fromDate = function(value) {\n this.year = value.getFullYear();\n this.month = value.getMonth();\n this.day = value.getDate();\n this.hours = value.getHours();\n this.minutes = value.getMinutes();\n this.seconds = value.getSeconds();\n this.milliseconds = value.getMilliseconds();\n return this;\n };\n\n ParseDate.prototype.toDate = function() {\n return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n };\n\n var proto = ParseDate.prototype;\n\n function noop() {\n }\n\n function isNumeric(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n function indexOfCaseInsensitive(array, value) {\n var len = array.length, str=value.toString().toLowerCase();\n for (var i=0; i<len; i++) {\n if (array[i].toLowerCase() === str) { return i; }\n }\n return -1; // Return -1 per the \"Array.indexOf()\" method.\n }\n\n var defaults = this.defaults = {\n format: 'shortDate',\n strict: false\n };\n\n this.$get = function($locale, dateFilter) {\n\n var DateParserFactory = function(config) {\n\n var options = angular.extend({}, defaults, config);\n\n var $dateParser = {};\n\n var regExpMap = {\n 'sss' : '[0-9]{3}',\n 'ss' : '[0-5][0-9]',\n 's' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n 'mm' : '[0-5][0-9]',\n 'm' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n 'HH' : '[01][0-9]|2[0-3]',\n 'H' : options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]',\n 'hh' : '[0][1-9]|[1][012]',\n 'h' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n 'a' : 'AM|PM',\n 'EEEE' : $locale.DATETIME_FORMATS.DAY.join('|'),\n 'EEE' : $locale.DATETIME_FORMATS.SHORTDAY.join('|'),\n 'dd' : '0[1-9]|[12][0-9]|3[01]',\n 'd' : options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]',\n 'MMMM' : $locale.DATETIME_FORMATS.MONTH.join('|'),\n 'MMM' : $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n 'MM' : '0[1-9]|1[012]',\n 'M' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n 'yyyy' : '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',\n 'yy' : '[0-9]{2}',\n 'y' : options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}',\n };\n\n var setFnMap = {\n 'sss' : proto.setMilliseconds,\n 'ss' : proto.setSeconds,\n 's' : proto.setSeconds,\n 'mm' : proto.setMinutes,\n 'm' : proto.setMinutes,\n 'HH' : proto.setHours,\n 'H' : proto.setHours,\n 'hh' : proto.setHours,\n 'h' : proto.setHours,\n 'EEEE' : noop,\n 'EEE' : noop,\n 'dd' : proto.setDate,\n 'd' : proto.setDate,\n 'a' : function(value) { var hours = this.getHours() % 12; return this.setHours(value.match(/pm/i) ? hours + 12 : hours); },\n 'MMMM' : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.MONTH, value)); },\n 'MMM' : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.SHORTMONTH, value)); },\n 'MM' : function(value) { return this.setMonth(1 * value - 1); },\n 'M' : function(value) { return this.setMonth(1 * value - 1); },\n 'yyyy' : proto.setFullYear,\n 'yy' : function(value) { return this.setFullYear(2000 + 1 * value); },\n 'y' : proto.setFullYear\n };\n\n var regex, setMap;\n\n $dateParser.init = function() {\n $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;\n regex = regExpForFormat($dateParser.$format);\n setMap = setMapForFormat($dateParser.$format);\n };\n\n $dateParser.isValid = function(date) {\n if(angular.isDate(date)) return !isNaN(date.getTime());\n return regex.test(date);\n };\n\n $dateParser.parse = function(value, baseDate, format, timezone) {\n // check for date format special names\n if(format) format = $locale.DATETIME_FORMATS[format] || format;\n if(angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format, timezone);\n var formatRegex = format ? regExpForFormat(format) : regex;\n var formatSetMap = format ? setMapForFormat(format) : setMap;\n var matches = formatRegex.exec(value);\n if(!matches) return false;\n // use custom ParseDate object to set parsed values\n var date = baseDate && !isNaN(baseDate.getTime()) ? new ParseDate().fromDate(baseDate) : new ParseDate().fromDate(new Date(1970, 0, 1, 0));\n for(var i = 0; i < matches.length - 1; i++) {\n formatSetMap[i] && formatSetMap[i].call(date, matches[i+1]);\n }\n // convert back to native Date object\n var newDate = date.toDate();\n\n // check new native Date object for day values overflow\n if (parseInt(date.day, 10) !== newDate.getDate()) {\n return false;\n }\n\n return newDate;\n };\n\n $dateParser.getDateForAttribute = function(key, value) {\n var date;\n\n if(value === 'today') {\n var today = new Date();\n date = new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, (key === 'minDate' ? 0 : -1));\n } else if(angular.isString(value) && value.match(/^\".+\"$/)) { // Support {{ dateObj }}\n date = new Date(value.substr(1, value.length - 2));\n } else if(isNumeric(value)) {\n date = new Date(parseInt(value, 10));\n } else if (angular.isString(value) && 0 === value.length) { // Reset date\n date = key === 'minDate' ? -Infinity : +Infinity;\n } else {\n date = new Date(value);\n }\n\n return date;\n };\n\n $dateParser.getTimeForAttribute = function(key, value) {\n var time;\n\n if(value === 'now') {\n time = new Date().setFullYear(1970, 0, 1);\n } else if(angular.isString(value) && value.match(/^\".+\"$/)) {\n time = new Date(value.substr(1, value.length - 2)).setFullYear(1970, 0, 1);\n } else if(isNumeric(value)) {\n time = new Date(parseInt(value, 10)).setFullYear(1970, 0, 1);\n } else if (angular.isString(value) && 0 === value.length) { // Reset time\n time = key === 'minTime' ? -Infinity : +Infinity;\n } else {\n time = $dateParser.parse(value, new Date(1970, 0, 1, 0));\n }\n\n return time;\n };\n\n /* Handle switch to/from daylight saving.\n * Hours may be non-zero on daylight saving cut-over:\n * > 12 when midnight changeover, but then cannot generate\n * midnight datetime, so jump to 1AM, otherwise reset.\n * @param date (Date) the date to check\n * @return (Date) the corrected date\n *\n * __ copied from jquery ui datepicker __\n */\n $dateParser.daylightSavingAdjust = function(date) {\n if (!date) {\n return null;\n }\n date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n return date;\n };\n\n /* Correct the date for timezone offset.\n * @param date (Date) the date to adjust\n * @param timezone (string) the timezone to adjust for\n * @param undo (boolean) to add or subtract timezone offset\n * @return (Date) the corrected date\n */\n $dateParser.timezoneOffsetAdjust = function(date, timezone, undo) {\n if (!date) {\n return null;\n }\n // Right now, only 'UTC' is supported.\n if (timezone && timezone === 'UTC') {\n date = new Date(date.getTime());\n date.setMinutes(date.getMinutes() + (undo?-1:1)*date.getTimezoneOffset());\n }\n return date;\n };\n\n // Private functions\n\n function setMapForFormat(format) {\n var keys = Object.keys(setFnMap), i;\n var map = [], sortedMap = [];\n // Map to setFn\n var clonedFormat = format;\n for(i = 0; i < keys.length; i++) {\n if(format.split(keys[i]).length > 1) {\n var index = clonedFormat.search(keys[i]);\n format = format.split(keys[i]).join('');\n if(setFnMap[keys[i]]) {\n map[index] = setFnMap[keys[i]];\n }\n }\n }\n // Sort result map\n angular.forEach(map, function(v) {\n // conditional required since angular.forEach broke around v1.2.21\n // related pr: https://github.com/angular/angular.js/pull/8525\n if(v) sortedMap.push(v);\n });\n return sortedMap;\n }\n\n function escapeReservedSymbols(text) {\n return text.replace(/\\//g, '[\\\\/]').replace('/-/g', '[-]').replace(/\\./g, '[.]').replace(/\\\\s/g, '[\\\\s]');\n }\n\n function regExpForFormat(format) {\n var keys = Object.keys(regExpMap), i;\n\n var re = format;\n // Abstract replaces to avoid collisions\n for(i = 0; i < keys.length; i++) {\n re = re.split(keys[i]).join('${' + i + '}');\n }\n // Replace abstracted values\n for(i = 0; i < keys.length; i++) {\n re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');\n }\n format = escapeReservedSymbols(format);\n\n return new RegExp('^' + re + '$', ['i']);\n }\n\n $dateParser.init();\n return $dateParser;\n\n };\n\n return DateParserFactory;\n\n };\n\n});\n\n// Source: helpers/debounce.js\nangular.module('mgcrea.ngStrap.helpers.debounce', [])\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L693\n.factory('debounce', function($timeout) {\n return function(func, wait, immediate) {\n var timeout = null;\n return function() {\n var context = this,\n args = arguments,\n callNow = immediate && !timeout;\n if(timeout) {\n $timeout.cancel(timeout);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(!immediate) {\n func.apply(context, args);\n }\n }, wait, false);\n if(callNow) {\n func.apply(context, args);\n }\n return timeout;\n };\n };\n})\n\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L661\n.factory('throttle', function($timeout) {\n return function(func, wait, options) {\n var timeout = null;\n options || (options = {});\n return function() {\n var context = this,\n args = arguments;\n if(!timeout) {\n if(options.leading !== false) {\n func.apply(context, args);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(options.trailing !== false) {\n func.apply(context, args);\n }\n }, wait, false);\n }\n };\n };\n});\n\n// Source: helpers/dimensions.js\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n .factory('dimensions', function($document, $window) {\n\n var jqLite = angular.element;\n var fn = {};\n\n /**\n * Test the element nodeName\n * @param element\n * @param name\n */\n var nodeName = fn.nodeName = function(element, name) {\n return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();\n };\n\n /**\n * Returns the element computed style\n * @param element\n * @param prop\n * @param extra\n */\n fn.css = function(element, prop, extra) {\n var value;\n if (element.currentStyle) { //IE\n value = element.currentStyle[prop];\n } else if (window.getComputedStyle) {\n value = window.getComputedStyle(element)[prop];\n } else {\n value = element.style[prop];\n }\n return extra === true ? parseFloat(value) || 0 : value;\n };\n\n /**\n * Provides read-only equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.offset = function(element) {\n var boxRect = element.getBoundingClientRect();\n var docElement = element.ownerDocument;\n return {\n width: boxRect.width || element.offsetWidth,\n height: boxRect.height || element.offsetHeight,\n top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),\n left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)\n };\n };\n \n /**\n * Provides set equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip\n * @url http://api.jquery.com/offset/\n * @param element\n * @param options\n * @param i\n */\n fn.setOffset = function (element, options, i) {\n var curPosition,\n curLeft,\n curCSSTop,\n curTop,\n curOffset,\n curCSSLeft,\n calculatePosition,\n position = fn.css(element, 'position'),\n curElem = angular.element(element),\n props = {};\n \n // Set position first, in-case top/left are set even on static elem\n if (position === 'static') {\n element.style.position = 'relative';\n }\n \n curOffset = fn.offset(element);\n curCSSTop = fn.css(element, 'top');\n curCSSLeft = fn.css(element, 'left');\n calculatePosition = (position === 'absolute' || position === 'fixed') && \n (curCSSTop + curCSSLeft).indexOf('auto') > -1;\n \n // Need to be able to calculate position if either\n // top or left is auto and position is either absolute or fixed\n if (calculatePosition) {\n curPosition = fn.position(element);\n curTop = curPosition.top;\n curLeft = curPosition.left;\n } else {\n curTop = parseFloat(curCSSTop) || 0;\n curLeft = parseFloat(curCSSLeft) || 0;\n }\n \n if (angular.isFunction(options)) {\n options = options.call(element, i, curOffset);\n }\n \n if (options.top !== null ) {\n props.top = (options.top - curOffset.top) + curTop;\n }\n if ( options.left !== null ) {\n props.left = (options.left - curOffset.left) + curLeft;\n }\n\n if ('using' in options) {\n options.using.call(curElem, props);\n } else {\n curElem.css({\n top: props.top + 'px',\n left: props.left + 'px'\n });\n }\n };\n\n /**\n * Provides read-only equivalent of jQuery's position function\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.position = function(element) {\n\n var offsetParentRect = {top: 0, left: 0},\n offsetParentElement,\n offset;\n\n // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n if (fn.css(element, 'position') === 'fixed') {\n\n // We assume that getBoundingClientRect is available when computed position is fixed\n offset = element.getBoundingClientRect();\n\n } else {\n\n // Get *real* offsetParentElement\n offsetParentElement = offsetParent(element);\n\n // Get correct offsets\n offset = fn.offset(element);\n if (!nodeName(offsetParentElement, 'html')) {\n offsetParentRect = fn.offset(offsetParentElement);\n }\n\n // Add offsetParent borders\n offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);\n offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);\n }\n\n // Subtract parent offsets and element margins\n return {\n width: element.offsetWidth,\n height: element.offsetHeight,\n top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),\n left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)\n };\n\n };\n\n /**\n * Returns the closest, non-statically positioned offsetParent of a given element\n * @required-by fn.position\n * @param element\n */\n var offsetParent = function offsetParentElement(element) {\n var docElement = element.ownerDocument;\n var offsetParent = element.offsetParent || docElement;\n if(nodeName(offsetParent, '#document')) return docElement.documentElement;\n while(offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {\n offsetParent = offsetParent.offsetParent;\n }\n return offsetParent || docElement.documentElement;\n };\n\n /**\n * Provides equivalent of jQuery's height function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/height/\n * @param element\n * @param outer\n */\n fn.height = function(element, outer) {\n var value = element.offsetHeight;\n if(outer) {\n value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);\n } else {\n value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);\n }\n return value;\n };\n\n /**\n * Provides equivalent of jQuery's width function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/width/\n * @param element\n * @param outer\n */\n fn.width = function(element, outer) {\n var value = element.offsetWidth;\n if(outer) {\n value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);\n } else {\n value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);\n }\n return value;\n };\n\n return fn;\n\n });\n\n// Source: helpers/parse-options.js\nangular.module('mgcrea.ngStrap.helpers.parseOptions', [])\n\n .provider('$parseOptions', function() {\n\n var defaults = this.defaults = {\n 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+(.*?))?$/\n };\n\n this.$get = function($parse, $q) {\n\n function ParseOptionsFactory(attr, config) {\n\n var $parseOptions = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n $parseOptions.$values = [];\n\n // Private vars\n var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;\n\n $parseOptions.init = function() {\n $parseOptions.$match = match = attr.match(options.regexp);\n displayFn = $parse(match[2] || match[1]),\n valueName = match[4] || match[6],\n keyName = match[5],\n groupByFn = $parse(match[3] || ''),\n valueFn = $parse(match[2] ? match[1] : valueName),\n valuesFn = $parse(match[7]);\n };\n\n $parseOptions.valuesFn = function(scope, controller) {\n return $q.when(valuesFn(scope, controller))\n .then(function(values) {\n $parseOptions.$values = values ? parseValues(values, scope) : {};\n return $parseOptions.$values;\n });\n };\n\n $parseOptions.displayValue = function(modelValue) {\n var scope = {};\n scope[valueName] = modelValue;\n return displayFn(scope);\n };\n\n // Private functions\n\n function parseValues(values, scope) {\n return values.map(function(match, index) {\n var locals = {}, label, value;\n locals[valueName] = match;\n label = displayFn(scope, locals);\n value = valueFn(scope, locals);\n return {label: label, value: value, index: index};\n });\n }\n\n $parseOptions.init();\n return $parseOptions;\n\n }\n\n return ParseOptionsFactory;\n\n };\n\n });\n\n// Source: helpers/raf.js\n(angular.version.minor < 3 && angular.version.dot < 14) && angular.module('ng')\n\n.factory('$$rAF', function($window, $timeout) {\n\n var requestAnimationFrame = $window.requestAnimationFrame ||\n $window.webkitRequestAnimationFrame ||\n $window.mozRequestAnimationFrame;\n\n var cancelAnimationFrame = $window.cancelAnimationFrame ||\n $window.webkitCancelAnimationFrame ||\n $window.mozCancelAnimationFrame ||\n $window.webkitCancelRequestAnimationFrame;\n\n var rafSupported = !!requestAnimationFrame;\n var raf = rafSupported ?\n function(fn) {\n var id = requestAnimationFrame(fn);\n return function() {\n cancelAnimationFrame(id);\n };\n } :\n function(fn) {\n var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n return function() {\n $timeout.cancel(timer);\n };\n };\n\n raf.supported = rafSupported;\n\n return raf;\n\n});\n\n// .factory('$$animateReflow', function($$rAF, $document) {\n\n// var bodyEl = $document[0].body;\n\n// return function(fn) {\n// //the returned function acts as the cancellation function\n// return $$rAF(function() {\n// //the line below will force the browser to perform a repaint\n// //so that all the animated elements within the animation frame\n// //will be properly updated and drawn on screen. This is\n// //required to perform multi-class CSS based animations with\n// //Firefox. DO NOT REMOVE THIS LINE.\n// var a = bodyEl.offsetWidth + 1;\n// fn();\n// });\n// };\n\n// });\n\n// Source: modal/modal.js\nangular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$modal', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n backdropAnimation: 'am-fade',\n prefixClass: 'modal',\n prefixEvent: 'modal',\n placement: 'top',\n template: 'modal/modal.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {\n\n var forEach = angular.forEach;\n var trim = String.prototype.trim;\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n var bodyElement = angular.element($window.document.body);\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n\n function ModalFactory(config) {\n\n var $modal = {};\n\n // Common vars\n var options = $modal.$options = angular.extend({}, defaults, config);\n $modal.$promise = fetchTemplate(options.template);\n var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(!options.element && !options.container) {\n options.container = 'body';\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $modal.$id = options.id || options.element && options.element.attr('id') || '';\n\n // Support scope as string options\n forEach(['title', 'content'], function(key) {\n if(options[key]) scope[key] = $sce.trustAsHtml(options[key]);\n });\n\n // Provide scope helpers\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $modal.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $modal.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $modal.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $modal.$isShown = scope.$isShown = false;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $modal.$promise = $modal.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);\n // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n if(!config.template) contentEl.next().remove();\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize modal\n var modalLinker, modalElement;\n var backdropElement = angular.element('<div class=\"' + options.prefixClass + '-backdrop\"/>');\n backdropElement.css({position:'fixed', top:'0px', left:'0px', bottom:'0px', right:'0px', 'z-index': 1038});\n $modal.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n modalLinker = $compile(template);\n $modal.init();\n });\n\n $modal.init = function() {\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n $modal.show();\n });\n }\n\n };\n\n $modal.destroy = function() {\n\n // Remove element\n if(modalElement) {\n modalElement.remove();\n modalElement = null;\n }\n if(backdropElement) {\n backdropElement.remove();\n backdropElement = null;\n }\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $modal.show = function() {\n if($modal.$isShown) return;\n\n var parent, after;\n if(angular.isElement(options.container)) {\n parent = options.container;\n after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;\n } else {\n if (options.container) {\n parent = findElement(options.container);\n after = parent[0] && parent[0].lastChild ? angular.element(parent[0].lastChild) : null;\n } else {\n parent = null;\n after = options.element;\n }\n }\n\n // Fetch a cloned element linked from template\n modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\n\n if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n return;\n }\n\n // Set the initial positioning.\n modalElement.css({display: 'block'}).addClass(options.placement);\n\n // Options: animation\n if(options.animation) {\n if(options.backdrop) {\n backdropElement.addClass(options.backdropAnimation);\n }\n modalElement.addClass(options.animation);\n }\n\n if(options.backdrop) {\n $animate.enter(backdropElement, bodyElement, null);\n }\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.enter(modalElement, parent, after, enterAnimateCallback);\n if(promise && promise.then) promise.then(enterAnimateCallback);\n\n $modal.$isShown = scope.$isShown = true;\n safeDigest(scope);\n // Focus once the enter-animation has started\n // Weird PhantomJS bug hack\n var el = modalElement[0];\n requestAnimationFrame(function() {\n el.focus();\n });\n\n bodyElement.addClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n }\n\n // Bind events\n if(options.backdrop) {\n modalElement.on('click', hideOnBackdropClick);\n backdropElement.on('click', hideOnBackdropClick);\n backdropElement.on('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.on('keyup', $modal.$onKeyUp);\n }\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $modal);\n }\n\n $modal.hide = function() {\n if(!$modal.$isShown) return;\n\n if(scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {\n return;\n }\n var promise = $animate.leave(modalElement, leaveAnimateCallback);\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n if(options.backdrop) {\n $animate.leave(backdropElement);\n }\n $modal.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.backdrop) {\n modalElement.off('click', hideOnBackdropClick);\n backdropElement.off('click', hideOnBackdropClick);\n backdropElement.off('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.off('keyup', $modal.$onKeyUp);\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $modal);\n bodyElement.removeClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n }\n }\n\n $modal.toggle = function() {\n\n $modal.$isShown ? $modal.hide() : $modal.show();\n\n };\n\n $modal.focus = function() {\n modalElement[0].focus();\n };\n\n // Protected methods\n\n $modal.$onKeyUp = function(evt) {\n\n if (evt.which === 27 && $modal.$isShown) {\n $modal.hide();\n evt.stopPropagation();\n }\n\n };\n\n // Private methods\n\n function hideOnBackdropClick(evt) {\n if(evt.target !== evt.currentTarget) return;\n options.backdrop === 'static' ? $modal.focus() : $modal.hide();\n }\n\n function preventEventDefault(evt) {\n evt.preventDefault();\n }\n\n return $modal;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return ModalFactory;\n\n };\n\n })\n\n .directive('bsModal', function($window, $sce, $modal) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsModal && scope.$watch(attr.bsModal, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize modal\n var modal = $modal(options);\n\n // Trigger\n element.on(attr.trigger || 'click', modal.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (modal) modal.destroy();\n options = null;\n modal = null;\n });\n\n }\n };\n\n });\n\n// Source: navbar/navbar.js\nangular.module('mgcrea.ngStrap.navbar', [])\n\n .provider('$navbar', function() {\n\n var defaults = this.defaults = {\n activeClass: 'active',\n routeAttr: 'data-match-route',\n strict: false\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsNavbar', function($window, $location, $navbar) {\n\n var defaults = $navbar.defaults;\n\n return {\n restrict: 'A',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = angular.copy(defaults);\n angular.forEach(Object.keys(defaults), function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Watch for the $location\n scope.$watch(function() {\n\n return $location.path();\n\n }, function(newValue, oldValue) {\n\n var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');\n\n angular.forEach(liElements, function(li) {\n\n var liElement = angular.element(li);\n var pattern = liElement.attr(options.routeAttr).replace('/', '\\\\/');\n if(options.strict) {\n pattern = '^' + pattern + '$';\n }\n var regexp = new RegExp(pattern, 'i');\n\n if(regexp.test(newValue)) {\n liElement.addClass(options.activeClass);\n } else {\n liElement.removeClass(options.activeClass);\n }\n\n });\n\n });\n\n }\n\n };\n\n });\n\n// Source: popover/popover.js\nangular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$popover', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n // uncommenting the next two lines will break backwards compatability\n // prefixClass: 'popover',\n // prefixEvent: 'popover',\n container: false,\n target: false,\n placement: 'right',\n template: 'popover/popover.tpl.html',\n contentTemplate: false,\n trigger: 'click',\n keyboard: true,\n html: false,\n title: '',\n content: '',\n delay: 0,\n autoClose: false\n };\n\n this.$get = function($tooltip) {\n\n function PopoverFactory(element, config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n var $popover = $tooltip(element, options);\n\n // Support scope as string options [/*title, */content]\n if(options.content) {\n $popover.$scope.content = options.content;\n }\n\n return $popover;\n\n }\n\n return PopoverFactory;\n\n };\n\n })\n\n .directive('bsPopover', function($window, $sce, $popover) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'customClass', 'autoClose', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoClose'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n });\n });\n\n // Support scope as an object\n attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);\n newValue === true ? popover.show() : popover.hide();\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n popover.setViewport(newValue);\n });\n\n // Initialize popover\n var popover = $popover(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (popover) popover.destroy();\n options = null;\n popover = null;\n });\n\n }\n };\n\n });\n\n// Source: scrollspy/scrollspy.js\nangular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', 'mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$scrollspy', function() {\n\n // Pool of registered spies\n var spies = this.$$spies = {};\n\n var defaults = this.defaults = {\n debounce: 150,\n throttle: 100,\n offset: 100\n };\n\n this.$get = function($window, $document, $rootScope, dimensions, debounce, throttle) {\n\n var windowEl = angular.element($window);\n var docEl = angular.element($document.prop('documentElement'));\n var bodyEl = angular.element($window.document.body);\n\n // Helper functions\n\n function nodeName(element, name) {\n return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();\n }\n\n function ScrollSpyFactory(config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n if(!options.element) options.element = bodyEl;\n var isWindowSpy = nodeName(options.element, 'body');\n var scrollEl = isWindowSpy ? windowEl : options.element;\n var scrollId = isWindowSpy ? 'window' : options.id;\n\n // Use existing spy\n if(spies[scrollId]) {\n spies[scrollId].$$count++;\n return spies[scrollId];\n }\n\n var $scrollspy = {};\n\n // Private vars\n var unbindViewContentLoaded, unbindIncludeContentLoaded;\n var trackedElements = $scrollspy.$trackedElements = [];\n var sortedElements = [];\n var activeTarget;\n var debouncedCheckPosition;\n var throttledCheckPosition;\n var debouncedCheckOffsets;\n var viewportHeight;\n var scrollTop;\n\n $scrollspy.init = function() {\n\n // Setup internal ref counter\n this.$$count = 1;\n\n // Bind events\n debouncedCheckPosition = debounce(this.checkPosition, options.debounce);\n throttledCheckPosition = throttle(this.checkPosition, options.throttle);\n scrollEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', debouncedCheckPosition);\n scrollEl.on('scroll', throttledCheckPosition);\n\n debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);\n unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);\n unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);\n debouncedCheckOffsets();\n\n // Register spy for reuse\n if(scrollId) {\n spies[scrollId] = $scrollspy;\n }\n\n };\n\n $scrollspy.destroy = function() {\n\n // Check internal ref counter\n this.$$count--;\n if(this.$$count > 0) {\n return;\n }\n\n // Unbind events\n scrollEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', debouncedCheckPosition);\n scrollEl.off('scroll', throttledCheckPosition);\n unbindViewContentLoaded();\n unbindIncludeContentLoaded();\n if (scrollId) {\n delete spies[scrollId];\n }\n };\n\n $scrollspy.checkPosition = function() {\n\n // Not ready yet\n if(!sortedElements.length) return;\n\n // Calculate the scroll position\n scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;\n\n // Calculate the viewport height for use by the components\n viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));\n\n // Activate first element if scroll is smaller\n if(scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {\n return $scrollspy.$activateElement(sortedElements[0]);\n }\n\n // Activate proper element\n for (var i = sortedElements.length; i--;) {\n if(angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) continue;\n if(activeTarget === sortedElements[i].target) continue;\n if(scrollTop < sortedElements[i].offsetTop) continue;\n if(sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) continue;\n return $scrollspy.$activateElement(sortedElements[i]);\n }\n\n };\n\n $scrollspy.checkPositionWithEventLoop = function() {\n // IE 9 throws an error if we use 'this' instead of '$scrollspy'\n // in this setTimeout call\n setTimeout($scrollspy.checkPosition, 1);\n };\n\n // Protected methods\n\n $scrollspy.$activateElement = function(element) {\n if(activeTarget) {\n var activeElement = $scrollspy.$getTrackedElement(activeTarget);\n if(activeElement) {\n activeElement.source.removeClass('active');\n if(nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {\n activeElement.source.parent().parent().removeClass('active');\n }\n }\n }\n activeTarget = element.target;\n element.source.addClass('active');\n if(nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {\n element.source.parent().parent().addClass('active');\n }\n };\n\n $scrollspy.$getTrackedElement = function(target) {\n return trackedElements.filter(function(obj) {\n return obj.target === target;\n })[0];\n };\n\n // Track offsets behavior\n\n $scrollspy.checkOffsets = function() {\n\n angular.forEach(trackedElements, function(trackedElement) {\n var targetElement = document.querySelector(trackedElement.target);\n trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;\n if(options.offset && trackedElement.offsetTop !== null) trackedElement.offsetTop -= options.offset * 1;\n });\n\n sortedElements = trackedElements\n .filter(function(el) {\n return el.offsetTop !== null;\n })\n .sort(function(a, b) {\n return a.offsetTop - b.offsetTop;\n });\n\n debouncedCheckPosition();\n\n };\n\n $scrollspy.trackElement = function(target, source) {\n trackedElements.push({target: target, source: source});\n };\n\n $scrollspy.untrackElement = function(target, source) {\n var toDelete;\n for (var i = trackedElements.length; i--;) {\n if(trackedElements[i].target === target && trackedElements[i].source === source) {\n toDelete = i;\n break;\n }\n }\n trackedElements = trackedElements.splice(toDelete, 1);\n };\n\n $scrollspy.activate = function(i) {\n trackedElements[i].addClass('active');\n };\n\n // Initialize plugin\n\n $scrollspy.init();\n return $scrollspy;\n\n }\n\n return ScrollSpyFactory;\n\n };\n\n })\n\n .directive('bsScrollspy', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'EAC',\n link: function postLink(scope, element, attr) {\n\n var options = {scope: scope};\n angular.forEach(['offset', 'target'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n var scrollspy = $scrollspy(options);\n scrollspy.trackElement(options.target, element);\n\n scope.$on('$destroy', function() {\n if (scrollspy) {\n scrollspy.untrackElement(options.target, element);\n scrollspy.destroy();\n }\n options = null;\n scrollspy = null;\n });\n\n }\n };\n\n })\n\n\n .directive('bsScrollspyList', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'A',\n compile: function postLink(element, attr) {\n var children = element[0].querySelectorAll('li > a[href]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));\n });\n }\n\n };\n\n });\n\n// Source: select/select.js\nangular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$select', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'select',\n prefixEvent: '$select',\n placement: 'bottom-left',\n template: 'select/select.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n multiple: false,\n allNoneButtons: false,\n sort: true,\n caretHtml: '&nbsp;<span class=\"caret\"></span>',\n placeholder: 'Choose among the following...',\n allText: 'All',\n noneText: 'None',\n maxLength: 3,\n maxLengthHtml: 'selected',\n iconCheckmark: 'glyphicon glyphicon-ok'\n };\n\n this.$get = function($window, $document, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n\n function SelectFactory(element, controller, config) {\n\n var $select = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $select = $tooltip(element, options);\n var scope = $select.$scope;\n\n scope.$matches = [];\n if (options.multiple) {\n scope.$activeIndex = [];\n }\n else {\n scope.$activeIndex = -1;\n }\n scope.$isMultiple = options.multiple;\n scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n scope.$iconCheckmark = options.iconCheckmark;\n scope.$allText = options.allText;\n scope.$noneText = options.noneText;\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $select.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $select.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $select.$isVisible();\n };\n\n scope.$isActive = function(index) {\n return $select.$isActive(index);\n };\n\n scope.$selectAll = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (!scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n scope.$selectNone = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n // Public methods\n\n $select.update = function(matches) {\n scope.$matches = matches;\n $select.$updateActiveIndex();\n };\n\n $select.activate = function(index) {\n if(options.multiple) {\n $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);\n if(options.sort) scope.$activeIndex.sort();\n } else {\n scope.$activeIndex = index;\n }\n return scope.$activeIndex;\n };\n\n $select.select = function(index) {\n var value = scope.$matches[index].value;\n scope.$apply(function() {\n $select.activate(index);\n if(options.multiple) {\n controller.$setViewValue(scope.$activeIndex.map(function(index) {\n return scope.$matches[index].value;\n }));\n } else {\n controller.$setViewValue(value);\n // Hide if single select\n $select.hide();\n }\n });\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $select);\n };\n\n // Protected methods\n\n $select.$updateActiveIndex = function() {\n if(controller.$modelValue && scope.$matches.length) {\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n scope.$activeIndex = controller.$modelValue.map(function(value) {\n return $select.$getIndex(value);\n });\n } else {\n scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n }\n } else if(scope.$activeIndex >= scope.$matches.length) {\n scope.$activeIndex = options.multiple ? [] : 0;\n }\n };\n\n $select.$isVisible = function() {\n if(!options.minLength || !controller) {\n return scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && controller.$viewValue.length >= options.minLength;\n };\n\n $select.$isActive = function(index) {\n if(options.multiple) {\n return scope.$activeIndex.indexOf(index) !== -1;\n } else {\n return scope.$activeIndex === index;\n }\n };\n\n $select.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $select.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n targetEl.triggerHandler('click');\n }\n };\n\n $select.$onKeyDown = function(evt) {\n if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // release focus on tab\n if (options.multiple && evt.keyCode === 9) {\n return $select.hide();\n }\n\n // Select with enter\n if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n return $select.select(scope.$activeIndex);\n }\n\n if (!options.multiple) {\n // Navigate with keyboard\n if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 38 && scope.$activeIndex < 0) scope.$activeIndex = scope.$matches.length - 1;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n }\n };\n\n // Overrides\n\n var _show = $select.show;\n $select.show = function() {\n _show();\n if(options.multiple) {\n $select.$element.addClass('select-multiple');\n }\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $select.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $select.hide;\n $select.hide = function() {\n if(!options.multiple && !controller.$modelValue) {\n scope.$activeIndex = -1;\n }\n $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $select.$onKeyDown);\n }\n _hide(true);\n };\n\n return $select;\n\n }\n\n SelectFactory.defaults = defaults;\n return SelectFactory;\n\n };\n\n })\n\n .directive('bsSelect', function($window, $parse, $q, $select, $parseOptions) {\n\n var defaults = $select.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, placeholder: defaults.placeholder};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'placeholder', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id', 'sort', 'caretHtml', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'allNoneButtons', 'sort'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Only parse data-multiple. Angular sets existence attributes to true (multiple/required/etc), they apply this\n // to data-multiple as well for some reason, so we'll parse this ourselves and disregard multiple\n var dataMultiple = element.attr('data-multiple');\n if(angular.isDefined(dataMultiple)) {\n if(falseValueRegExp.test(dataMultiple))\n options.multiple = false;\n else\n options.multiple = dataMultiple;\n }\n\n // Add support for select markup\n if(element[0].nodeName.toLowerCase() === 'select') {\n var inputEl = element;\n inputEl.css('display', 'none');\n element = angular.element('<button type=\"button\" class=\"btn btn-default\"></button>');\n inputEl.after(element);\n }\n\n // Build proper bsOptions\n var parsedOptions = $parseOptions(attr.bsOptions);\n\n // Initialize select\n var select = $select(element, controller, options);\n\n // Watch bsOptions values before filtering for changes\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n scope.$watchCollection(watchedOptions, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n select.update(values);\n controller.$render();\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n select.$updateActiveIndex();\n controller.$render();\n }, true);\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var selected, index;\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n selected = controller.$modelValue.map(function(value) {\n index = select.$getIndex(value);\n return angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }).filter(angular.isDefined);\n if(selected.length > (options.maxLength || defaults.maxLength)) {\n selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml);\n } else {\n selected = selected.join(', ');\n }\n } else {\n index = select.$getIndex(controller.$modelValue);\n selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }\n element.html((selected ? selected : options.placeholder) + (options.caretHtml ? options.caretHtml : defaults.caretHtml));\n };\n\n if(options.multiple){\n controller.$isEmpty = function(value){\n return !value || value.length === 0;\n };\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (select) select.destroy();\n options = null;\n select = null;\n });\n\n }\n };\n\n });\n\n// Source: tab/tab.js\nangular.module('mgcrea.ngStrap.tab', [])\n\n .provider('$tab', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n template: 'tab/tab.tpl.html',\n navClass: 'nav-tabs',\n activeClass: 'active'\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'navClass', 'activeClass'], function(key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // Publish options on scope\n $scope.$navClass = self.$options.navClass;\n $scope.$activeClass = self.$options.activeClass;\n\n self.$panes = $scope.$panes = [];\n\n // Please use $activePaneChangeListeners if you use `bsActivePane`\n // Because we removed `ngModel` as default, we rename viewChangeListeners to\n // activePaneChangeListeners to make more sense.\n self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n if(angular.isUndefined(self.$panes.$active)) {\n $scope.$setActive(pane.name || 0);\n }\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var active = self.$panes.$active;\n var activeIndex;\n if(angular.isString(active)) {\n activeIndex = self.$panes.map(function(pane) {\n return pane.name;\n }).indexOf(active);\n } else {\n activeIndex = self.$panes.$active;\n }\n\n // remove pane from $panes array\n self.$panes.splice(index, 1);\n\n if (index < activeIndex) {\n // we removed a pane before the active pane, so we need to\n // decrement the active pane index\n activeIndex--;\n }\n else if (index === activeIndex && activeIndex === self.$panes.length) {\n // we remove the active pane and it was the one at the end,\n // so select the previous one\n activeIndex--;\n }\n if(activeIndex >= 0 && activeIndex < self.$panes.length) {\n self.$setActive(self.$panes[activeIndex].name || activeIndex);\n } else {\n self.$setActive();\n }\n };\n\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$activePaneChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$isActive = $scope.$isActive = function($pane, $index) {\n return self.$panes.$active === $pane.name || self.$panes.$active === $index;\n };\n\n };\n\n this.$get = function() {\n var $tab = {};\n $tab.defaults = defaults;\n $tab.controller = controller;\n return $tab;\n };\n\n })\n\n .directive('bsTabs', function($window, $animate, $tab, $parse) {\n\n var defaults = $tab.defaults;\n\n return {\n require: ['?ngModel', 'bsTabs'],\n transclude: true,\n scope: true,\n controller: ['$scope', '$element', '$attrs', $tab.controller],\n templateUrl: function(element, attr) {\n return attr.template || defaults.template;\n },\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // 'ngModel' does interfere with form validation\n // and status, use `bsActivePane` instead to avoid it\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n bsTabsCtrl.$setActive(modelValue);\n return modelValue;\n });\n\n }\n\n if (attrs.bsActivePane) {\n // adapted from angularjs ngModelController bindings\n // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n // Update bsActivePane value with change\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n });\n\n // watch bsActivePane for value changes\n scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n bsTabsCtrl.$setActive(newValue);\n }, true);\n }\n }\n };\n\n })\n\n .directive('bsPane', function($window, $animate, $sce) {\n\n return {\n require: ['^?ngModel', '^bsTabs'],\n scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // Add base class\n element.addClass('tab-pane');\n\n // Observe title attribute for change\n attrs.$observe('title', function(newValue, oldValue) {\n scope.title = $sce.trustAsHtml(newValue);\n });\n\n // Save tab name into scope\n scope.name = attrs.name;\n\n // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\n }\n\n attrs.$observe('disabled', function(newValue, oldValue) {\n scope.disabled = scope.$eval(newValue);\n });\n\n // Push pane to parent bsTabs controller\n bsTabsCtrl.$push(scope);\n\n // remove pane from tab controller when pane is destroyed\n scope.$on('$destroy', function() {\n bsTabsCtrl.$remove(scope);\n });\n\n function render() {\n var index = bsTabsCtrl.$panes.indexOf(scope);\n $animate[bsTabsCtrl.$isActive(scope, index) ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n\n// Source: timepicker/timepicker.js\nangular.module('mgcrea.ngStrap.timepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$timepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'timepicker',\n prefixClass: 'timepicker',\n placement: 'bottom-left',\n template: 'timepicker/timepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: true,\n timeType: 'date',\n timeFormat: 'shortTime',\n timezone: null,\n modelTimeFormat: null,\n autoclose: false,\n minTime: -Infinity,\n maxTime: +Infinity,\n length: 5,\n hourStep: 1,\n minuteStep: 5,\n secondStep: 5,\n roundDisplay: false,\n iconUp: 'glyphicon glyphicon-chevron-up',\n iconDown: 'glyphicon glyphicon-chevron-down',\n arrowBehavior: 'pager'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function timepickerFactory(element, controller, config) {\n\n var $timepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $timepicker.$options;\n var scope = $timepicker.$scope;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n function floorMinutes(time)\n {\n // coeff used to floor current time to nearest minuteStep interval\n var coeff = 1000 * 60 * options.minuteStep;\n return new Date(Math.floor(time.getTime() / coeff) * coeff);\n }\n\n // View vars\n\n var selectedIndex = 0;\n var defaultDate = options.roundDisplay ? floorMinutes(new Date()) : new Date();\n var startDate = controller.$dateValue || defaultDate;\n var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n var hoursFormat = $dateFormatter.hoursFormat(format),\n timeSeparator = $dateFormatter.timeSeparator(format),\n minutesFormat = $dateFormatter.minutesFormat(format),\n secondsFormat = $dateFormatter.secondsFormat(format),\n showSeconds = $dateFormatter.showSeconds(format),\n showAM = $dateFormatter.showAM(format);\n\n scope.$iconUp = options.iconUp;\n scope.$iconDown = options.iconDown;\n\n // Scope methods\n\n scope.$select = function(date, index) {\n $timepicker.select(date, index);\n };\n scope.$moveIndex = function(value, index) {\n $timepicker.$moveIndex(value, index);\n };\n scope.$switchMeridian = function(date) {\n $timepicker.switchMeridian(date);\n };\n\n // Public methods\n\n $timepicker.update = function(date) {\n // console.warn('$timepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $timepicker.$date = date;\n angular.extend(viewDate, {hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds(), millisecond: date.getMilliseconds()});\n $timepicker.$build();\n } else if(!$timepicker.$isBuilt) {\n $timepicker.$build();\n }\n };\n\n $timepicker.select = function(date, index, keep) {\n // console.warn('$timepicker.select', date, scope.$mode);\n if(!controller.$dateValue || isNaN(controller.$dateValue.getTime())) controller.$dateValue = new Date(1970, 0, 1);\n if(!angular.isDate(date)) date = new Date(date);\n if(index === 0) controller.$dateValue.setHours(date.getHours());\n else if(index === 1) controller.$dateValue.setMinutes(date.getMinutes());\n else if(index === 2) controller.$dateValue.setSeconds(date.getSeconds());\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $timepicker.hide(true); });\n }\n };\n\n $timepicker.switchMeridian = function(date) {\n if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) {\n return;\n }\n var hours = (date || controller.$dateValue).getHours();\n controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12);\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n };\n\n // Protected methods\n\n $timepicker.$build = function() {\n // console.warn('$timepicker.$build() viewDate=%o', viewDate);\n var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n var hours = [], hour;\n for(i = 0; i < options.length; i++) {\n hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);\n hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});\n }\n var minutes = [], minute;\n for(i = 0; i < options.length; i++) {\n minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);\n minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n }\n var seconds = [], second;\n for(i = 0; i < options.length; i++) {\n second = new Date(1970, 0, 1, 0, 0, viewDate.second - (midIndex - i) * options.secondStep);\n seconds.push({date: second, label: formatDate(second, secondsFormat), selected: $timepicker.$date && $timepicker.$isSelected(second, 2), disabled: $timepicker.$isDisabled(second, 2)});\n }\n\n var rows = [];\n for(i = 0; i < options.length; i++) {\n if (showSeconds) {\n rows.push([hours[i], minutes[i], seconds[i]]);\n } else {\n rows.push([hours[i], minutes[i]]);\n }\n }\n scope.rows = rows;\n scope.showSeconds = showSeconds;\n scope.showAM = showAM;\n scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n scope.timeSeparator = timeSeparator;\n $timepicker.$isBuilt = true;\n };\n\n $timepicker.$isSelected = function(date, index) {\n if(!$timepicker.$date) return false;\n else if(index === 0) {\n return date.getHours() === $timepicker.$date.getHours();\n } else if(index === 1) {\n return date.getMinutes() === $timepicker.$date.getMinutes();\n } else if(index === 2) {\n return date.getSeconds() === $timepicker.$date.getSeconds();\n }\n };\n\n $timepicker.$isDisabled = function(date, index) {\n var selectedTime;\n if(index === 0) {\n selectedTime = date.getTime() + viewDate.minute * 6e4 + viewDate.second * 1e3;\n } else if(index === 1) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.second * 1e3;\n } else if(index === 2) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.minute * 6e4;\n }\n return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1;\n };\n\n scope.$arrowAction = function (value, index) {\n if (options.arrowBehavior === 'picker') {\n $timepicker.$setTimeByStep(value,index);\n } else {\n $timepicker.$moveIndex(value,index);\n }\n };\n\n $timepicker.$setTimeByStep = function(value, index) {\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n if (index === 0) {\n newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n }\n else if (index === 1) {\n newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\n }\n else if (index === 2) {\n newDate.setSeconds(seconds - (parseInt(options.secondStep, 10) * value));\n }\n $timepicker.select(newDate, index, true);\n };\n\n $timepicker.$moveIndex = function(value, index) {\n var targetDate;\n if(index === 0) {\n targetDate = new Date(1970, 0, 1, viewDate.hour + (value * options.length), viewDate.minute, viewDate.second);\n angular.extend(viewDate, {hour: targetDate.getHours()});\n } else if(index === 1) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + (value * options.length * options.minuteStep), viewDate.second);\n angular.extend(viewDate, {minute: targetDate.getMinutes()});\n } else if(index === 2) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute, viewDate.second + (value * options.length * options.secondStep));\n angular.extend(viewDate, {second: targetDate.getSeconds()});\n }\n $timepicker.$build();\n };\n\n $timepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n if(evt.target.nodeName.toLowerCase() !== 'input') evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $timepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Close on enter\n if(evt.keyCode === 13) return $timepicker.hide(true);\n\n // Navigate with keyboard\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n var sepLength = 1;\n var lateralMove = /(37|39)/.test(evt.keyCode);\n var count = 2 + showSeconds * 1 + showAM * 1;\n\n // Navigate indexes (left, right)\n if (lateralMove) {\n if(evt.keyCode === 37) selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1;\n else if(evt.keyCode === 39) selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0;\n }\n\n // Update values (up, down)\n var selectRange = [0, hoursLength];\n var incr = 0;\n if (evt.keyCode === 38) incr = -1;\n if (evt.keyCode === 40) incr = +1;\n var isSeconds = selectedIndex === 2 && showSeconds;\n var isMeridian = selectedIndex === 2 && !showSeconds || selectedIndex === 3 && showSeconds;\n if(selectedIndex === 0) {\n newDate.setHours(hours + incr*parseInt(options.hourStep, 10));\n // re-calculate hours length because we have changed hours value\n hoursLength = formatDate(newDate, hoursFormat).length;\n selectRange = [0, hoursLength];\n } else if(selectedIndex === 1) {\n newDate.setMinutes(minutes + incr*parseInt(options.minuteStep, 10));\n // re-calculate minutes length because we have changes minutes value\n minutesLength = formatDate(newDate, minutesFormat).length;\n selectRange = [hoursLength + sepLength, minutesLength];\n } else if(isSeconds) {\n newDate.setSeconds(seconds + incr*parseInt(options.secondStep, 10));\n // re-calculate seconds length because we have changes seconds value\n secondsLength = formatDate(newDate, secondsFormat).length;\n selectRange = [hoursLength + sepLength + minutesLength + sepLength, secondsLength];\n } else if(isMeridian) {\n if(!lateralMove) $timepicker.switchMeridian();\n selectRange = [hoursLength + sepLength + minutesLength + sepLength + (secondsLength + sepLength)*showSeconds, 2];\n }\n $timepicker.select(newDate, selectedIndex, true);\n createSelection(selectRange[0], selectRange[1]);\n parentScope.$digest();\n };\n\n // Private\n\n function createSelection(start, length) {\n var end = start + length;\n if(element[0].createTextRange) {\n var selRange = element[0].createTextRange();\n selRange.collapse(true);\n selRange.moveStart('character', start);\n selRange.moveEnd('character', end);\n selRange.select();\n } else if(element[0].setSelectionRange) {\n element[0].setSelectionRange(start, end);\n } else if(angular.isUndefined(element[0].selectionStart)) {\n element[0].selectionStart = start;\n element[0].selectionEnd = end;\n }\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $timepicker.init;\n $timepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'time');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $timepicker.destroy;\n $timepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $timepicker.show;\n $timepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $timepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $timepicker.hide;\n $timepicker.hide = function(blur) {\n if(!$timepicker.$isShown) return;\n $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $timepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $timepicker;\n\n }\n\n timepickerFactory.defaults = defaults;\n return timepickerFactory;\n\n };\n\n })\n\n\n .directive('bsTimepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n var defaults = $timepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'timeType', 'timeFormat', 'timezone', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'secondStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'roundDisplay', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative', 'roundDisplay'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!timepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(timepicker),?/i);\n newValue === true ? timepicker.show() : timepicker.hide();\n });\n\n // Initialize timepicker\n if(isNative && (options.useNative || defaults.useNative)) options.timeFormat = 'HH:mm';\n var timepicker = $timepicker(element, controller, options);\n options = timepicker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n // Initialize parser\n var dateParser = $dateParser({format: options.timeFormat, lang: lang});\n\n // Observe attributes for changes\n angular.forEach(['minTime', 'maxTime'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n !isNaN(timepicker.$options[key]) && timepicker.$build();\n validateAgainstMinMaxTime(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue);\n timepicker.update(controller.$dateValue);\n }, true);\n\n function validateAgainstMinMaxTime(parsedTime) {\n if (!angular.isDate(parsedTime)) return;\n var isMinValid = isNaN(options.minTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) >= options.minTime;\n var isMaxValid = isNaN(options.maxTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) <= options.maxTime;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(!isValid) {\n return;\n }\n controller.$dateValue = parsedTime;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n controller.$setValidity('date', true);\n return null;\n }\n var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedTime || isNaN(parsedTime.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxTime(parsedTime);\n }\n\n if(options.timeType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedTime, options.timezone, true);\n return formatDate(date, options.modelTimeFormat || options.timeFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.timeType === 'number') {\n return date.getTime();\n } else if(options.timeType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.timeType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.timeType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelTimeFormat);\n } else if(options.timeType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5);\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getTimeFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getTimeFormattedString());\n };\n\n function getTimeFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (timepicker) timepicker.destroy();\n options = null;\n timepicker = null;\n });\n\n }\n };\n\n });\n\n// Source: tooltip/tooltip.js\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$tooltip', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n prefixClass: 'tooltip',\n prefixEvent: 'tooltip',\n container: false,\n target: false,\n placement: 'top',\n template: 'tooltip/tooltip.tpl.html',\n contentTemplate: false,\n trigger: 'hover focus',\n keyboard: false,\n html: false,\n show: false,\n title: '',\n type: '',\n delay: 0,\n autoClose: false,\n bsEnabled: true,\n viewport: {\n selector: 'body',\n padding: 0\n }\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n var trim = String.prototype.trim;\n var isTouch = 'createTouch' in $window.document;\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n var $body = angular.element($window.document);\n\n function TooltipFactory(element, config) {\n\n var $tooltip = {};\n\n // Common vars\n var nodeName = element[0].nodeName.toLowerCase();\n var options = $tooltip.$options = angular.extend({}, defaults, config);\n $tooltip.$promise = fetchTemplate(options.template);\n var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(options.delay && angular.isString(options.delay)) {\n var split = options.delay.split(',').map(parseFloat);\n options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $tooltip.$id = options.id || element.attr('id') || '';\n\n // Support scope as string options\n if(options.title) {\n scope.title = $sce.trustAsHtml(options.title);\n }\n\n // Provide scope helpers\n scope.$setEnabled = function(isEnabled) {\n scope.$$postDigest(function() {\n $tooltip.setEnabled(isEnabled);\n });\n };\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $tooltip.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $tooltip.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $tooltip.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $tooltip.$isShown = scope.$isShown = false;\n\n // Private vars\n var timeout, hoverState;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $tooltip.$promise = $tooltip.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]);\n if(!contentEl.length) contentEl = findElement('[ng-bind=\"title\"]', templateEl[0]);\n contentEl.removeAttr('ng-bind').html(contentTemplate);\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize tooltip\n var tipLinker, tipElement, tipTemplate, tipContainer, tipScope;\n $tooltip.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n tipTemplate = template;\n tipLinker = $compile(template);\n $tooltip.init();\n });\n\n $tooltip.init = function() {\n\n // Options: delay\n if (options.delay && angular.isNumber(options.delay)) {\n options.delay = {\n show: options.delay,\n hide: options.delay\n };\n }\n\n // Replace trigger on touch devices ?\n // if(isTouch && options.trigger === defaults.trigger) {\n // options.trigger.replace(/hover/g, 'click');\n // }\n\n // Options : container\n if(options.container === 'self') {\n tipContainer = element;\n } else if(angular.isElement(options.container)) {\n tipContainer = options.container;\n } else if(options.container) {\n tipContainer = findElement(options.container);\n }\n\n // Options: trigger\n bindTriggerEvents();\n\n // Options: target\n if(options.target) {\n options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n }\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n options.trigger === 'focus' ? element[0].focus() : $tooltip.show();\n });\n }\n\n };\n\n $tooltip.destroy = function() {\n\n // Unbind events\n unbindTriggerEvents();\n\n // Remove element\n destroyTipElement();\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $tooltip.enter = function() {\n\n clearTimeout(timeout);\n hoverState = 'in';\n if (!options.delay || !options.delay.show) {\n return $tooltip.show();\n }\n\n timeout = setTimeout(function() {\n if (hoverState ==='in') $tooltip.show();\n }, options.delay.show);\n\n };\n\n $tooltip.show = function() {\n if (!options.bsEnabled || $tooltip.$isShown) return;\n\n scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n var parent, after;\n if (options.container) {\n parent = tipContainer;\n if (tipContainer[0].lastChild) {\n after = angular.element(tipContainer[0].lastChild);\n } else {\n after = null;\n }\n } else {\n parent = null;\n after = element;\n }\n\n\n // Hide any existing tipElement\n if(tipElement) destroyTipElement();\n // Fetch a cloned element linked from template\n tipScope = $tooltip.$scope.$new();\n tipElement = $tooltip.$element = tipLinker(tipScope, function(clonedElement, scope) {});\n\n // Set the initial positioning. Make the tooltip invisible\n // so IE doesn't try to focus on it off screen.\n tipElement.css({top: '-9999px', left: '-9999px', right: 'auto', display: 'block', visibility: 'hidden'});\n\n // Options: animation\n if(options.animation) tipElement.addClass(options.animation);\n // Options: type\n if(options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n // Options: custom classes\n if(options.customClass) tipElement.addClass(options.customClass);\n\n // Append the element, without any animations. If we append\n // using $animate.enter, some of the animations cause the placement\n // to be off due to the transforms.\n after ? after.after(tipElement) : parent.prepend(tipElement);\n\n $tooltip.$isShown = scope.$isShown = true;\n safeDigest(scope);\n\n // Now, apply placement\n $tooltip.$applyPlacement();\n\n // Once placed, animate it.\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.enter(tipElement, parent, after, enterAnimateCallback);\n if(promise && promise.then) promise.then(enterAnimateCallback);\n safeDigest(scope);\n\n $$rAF(function () {\n // Once the tooltip is placed and the animation starts, make the tooltip visible\n if(tipElement) tipElement.css({visibility: 'visible'});\n });\n\n // Bind events\n if(options.keyboard) {\n if(options.trigger !== 'focus') {\n $tooltip.focus();\n }\n bindKeyboardEvents();\n }\n\n if(options.autoClose) {\n bindAutoCloseEvents();\n }\n\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $tooltip);\n }\n\n $tooltip.leave = function() {\n\n clearTimeout(timeout);\n hoverState = 'out';\n if (!options.delay || !options.delay.hide) {\n return $tooltip.hide();\n }\n timeout = setTimeout(function () {\n if (hoverState === 'out') {\n $tooltip.hide();\n }\n }, options.delay.hide);\n\n };\n\n var _blur;\n var _tipToHide;\n $tooltip.hide = function(blur) {\n\n if(!$tooltip.$isShown) return;\n scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n\n // store blur value for leaveAnimateCallback to use\n _blur = blur;\n\n // store current tipElement reference to use\n // in leaveAnimateCallback\n _tipToHide = tipElement;\n\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.leave(tipElement, leaveAnimateCallback);\n if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n $tooltip.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.keyboard && tipElement !== null) {\n unbindKeyboardEvents();\n }\n\n if(options.autoClose && tipElement !== null) {\n unbindAutoCloseEvents();\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\n\n // check if current tipElement still references\n // the same element when hide was called\n if (tipElement === _tipToHide) {\n // Allow to blur the input when hidden, like when pressing enter key\n if(_blur && options.trigger === 'focus') {\n return element[0].blur();\n }\n\n // clean up child scopes\n destroyTipElement();\n }\n }\n\n $tooltip.toggle = function() {\n $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter();\n };\n\n $tooltip.focus = function() {\n tipElement[0].focus();\n };\n\n $tooltip.setEnabled = function(isEnabled) {\n options.bsEnabled = isEnabled;\n };\n\n $tooltip.setViewport = function(viewport) {\n options.viewport = viewport;\n };\n\n // Protected methods\n\n $tooltip.$applyPlacement = function() {\n if(!tipElement) return;\n\n // Determine if we're doing an auto or normal placement\n var placement = options.placement,\n autoToken = /\\s?auto?\\s?/i,\n autoPlace = autoToken.test(placement);\n\n if (autoPlace) {\n placement = placement.replace(autoToken, '') || defaults.placement;\n }\n\n // Need to add the position class before we get\n // the offsets\n tipElement.addClass(options.placement);\n\n // Get the position of the target element\n // and the height and width of the tooltip so we can center it.\n var elementPosition = getPosition(),\n tipWidth = tipElement.prop('offsetWidth'),\n tipHeight = tipElement.prop('offsetHeight');\n\n // If we're auto placing, we need to check the positioning\n if (autoPlace) {\n var originalPlacement = placement;\n var container = options.container ? findElement(options.container) : element.parent();\n var containerPosition = getPosition(container);\n\n // Determine if the vertical placement\n if (originalPlacement.indexOf('bottom') >= 0 && elementPosition.bottom + tipHeight > containerPosition.bottom) {\n placement = originalPlacement.replace('bottom', 'top');\n } else if (originalPlacement.indexOf('top') >= 0 && elementPosition.top - tipHeight < containerPosition.top) {\n placement = originalPlacement.replace('top', 'bottom');\n }\n\n // Determine the horizontal placement\n // The exotic placements of left and right are opposite of the standard placements. Their arrows are put on the left/right\n // and flow in the opposite direction of their placement.\n if ((originalPlacement === 'right' || originalPlacement === 'bottom-left' || originalPlacement === 'top-left') &&\n elementPosition.right + tipWidth > containerPosition.width) {\n\n placement = originalPlacement === 'right' ? 'left' : placement.replace('left', 'right');\n } else if ((originalPlacement === 'left' || originalPlacement === 'bottom-right' || originalPlacement === 'top-right') &&\n elementPosition.left - tipWidth < containerPosition.left) {\n\n placement = originalPlacement === 'left' ? 'right' : placement.replace('right', 'left');\n }\n\n tipElement.removeClass(originalPlacement).addClass(placement);\n }\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n applyPlacement(tipPosition, placement);\n };\n\n $tooltip.$onKeyUp = function(evt) {\n if (evt.which === 27 && $tooltip.$isShown) {\n $tooltip.hide();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusKeyUp = function(evt) {\n if (evt.which === 27) {\n element[0].blur();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusElementMouseDown = function(evt) {\n evt.preventDefault();\n evt.stopPropagation();\n // Some browsers do not auto-focus buttons (eg. Safari)\n $tooltip.$isShown ? element[0].blur() : element[0].focus();\n };\n\n // bind/unbind events\n function bindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n angular.forEach(triggers, function(trigger) {\n if(trigger === 'click') {\n element.on('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n });\n }\n\n function unbindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n for (var i = triggers.length; i--;) {\n var trigger = triggers[i];\n if(trigger === 'click') {\n element.off('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n }\n }\n\n function bindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.on('keyup', $tooltip.$onKeyUp);\n } else {\n element.on('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n function unbindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.off('keyup', $tooltip.$onKeyUp);\n } else {\n element.off('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n var _autoCloseEventsBinded = false;\n function bindAutoCloseEvents() {\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // Stop propagation when clicking inside tooltip\n tipElement.on('click', stopEventPropagation);\n\n // Hide when clicking outside tooltip\n $body.on('click', $tooltip.hide);\n\n _autoCloseEventsBinded = true;\n }, 0, false);\n }\n\n function unbindAutoCloseEvents() {\n if (_autoCloseEventsBinded) {\n tipElement.off('click', stopEventPropagation);\n $body.off('click', $tooltip.hide);\n _autoCloseEventsBinded = false;\n }\n }\n\n function stopEventPropagation(event) {\n event.stopPropagation();\n }\n\n // Private methods\n\n function getPosition($element) {\n $element = $element || (options.target || element);\n\n var el = $element[0],\n isBody = el.tagName === 'BODY';\n\n var elRect = el.getBoundingClientRect();\n var rect = {};\n\n // IE8 has issues with angular.extend and using elRect directly.\n // By coping the values of elRect into a new object, we can continue to use extend\n for (var p in elRect) {\n // DO NOT use hasOwnProperty when inspecting the return of getBoundingClientRect.\n rect[p] = elRect[p];\n }\n\n if (rect.width === null) {\n // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n rect = angular.extend({}, rect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });\n }\n var elOffset = isBody ? { top: 0, left: 0 } : dimensions.offset(el),\n scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.prop('scrollTop') || 0 },\n outerDims = isBody ? { width: document.documentElement.clientWidth, height: $window.innerHeight } : null;\n\n return angular.extend({}, rect, scroll, outerDims, elOffset);\n }\n\n function getCalculatedOffset(placement, position, actualWidth, actualHeight) {\n var offset;\n var split = placement.split('-');\n\n switch (split[0]) {\n case 'right':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left + position.width\n };\n break;\n case 'bottom':\n offset = {\n top: position.top + position.height,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n case 'left':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left - actualWidth\n };\n break;\n default:\n offset = {\n top: position.top - actualHeight,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n }\n\n if(!split[1]) {\n return offset;\n }\n\n // Add support for corners @todo css\n if(split[0] === 'top' || split[0] === 'bottom') {\n switch (split[1]) {\n case 'left':\n offset.left = position.left;\n break;\n case 'right':\n offset.left = position.left + position.width - actualWidth;\n }\n } else if(split[0] === 'left' || split[0] === 'right') {\n switch (split[1]) {\n case 'top':\n offset.top = position.top - actualHeight;\n break;\n case 'bottom':\n offset.top = position.top + position.height;\n }\n }\n\n return offset;\n }\n\n function applyPlacement(offset, placement) {\n var tip = tipElement[0],\n width = tip.offsetWidth,\n height = tip.offsetHeight;\n\n // manually read margins because getBoundingClientRect includes difference\n var marginTop = parseInt(dimensions.css(tip, 'margin-top'), 10),\n marginLeft = parseInt(dimensions.css(tip, 'margin-left'), 10);\n\n // we must check for NaN for ie 8/9\n if (isNaN(marginTop)) marginTop = 0;\n if (isNaN(marginLeft)) marginLeft = 0;\n\n offset.top = offset.top + marginTop;\n offset.left = offset.left + marginLeft;\n\n // dimensions setOffset doesn't round pixel values\n // so we use setOffset directly with our own function\n dimensions.setOffset(tip, angular.extend({\n using: function (props) {\n tipElement.css({\n top: Math.round(props.top) + 'px',\n left: Math.round(props.left) + 'px',\n right: ''\n });\n }\n }, offset), 0);\n\n // check to see if placing tip in new offset caused the tip to resize itself\n var actualWidth = tip.offsetWidth,\n actualHeight = tip.offsetHeight;\n\n if (placement === 'top' && actualHeight !== height) {\n offset.top = offset.top + height - actualHeight;\n }\n\n // If it's an exotic placement, exit now instead of\n // applying a delta and changing the arrow\n if (/top-left|top-right|bottom-left|bottom-right/.test(placement)) return;\n\n var delta = getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);\n\n if (delta.left) {\n offset.left += delta.left;\n } else {\n offset.top += delta.top;\n }\n\n dimensions.setOffset(tip, offset);\n\n if (/top|right|bottom|left/.test(placement)) {\n var isVertical = /top|bottom/.test(placement),\n arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight,\n arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';\n\n replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical);\n }\n }\n\n function getViewportAdjustedDelta(placement, position, actualWidth, actualHeight) {\n var delta = { top: 0, left: 0 },\n $viewport = options.viewport && findElement(options.viewport.selector || options.viewport);\n\n if (!$viewport) {\n return delta;\n }\n\n var viewportPadding = options.viewport && options.viewport.padding || 0,\n viewportDimensions = getPosition($viewport);\n\n if (/right|left/.test(placement)) {\n var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll,\n bottomEdgeOffset = position.top + viewportPadding - viewportDimensions.scroll + actualHeight;\n if (topEdgeOffset < viewportDimensions.top) { // top overflow\n delta.top = viewportDimensions.top - topEdgeOffset;\n } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;\n }\n } else {\n var leftEdgeOffset = position.left - viewportPadding,\n rightEdgeOffset = position.left + viewportPadding + actualWidth;\n if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n delta.left = viewportDimensions.left - leftEdgeOffset;\n } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow\n delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;\n }\n }\n\n return delta;\n }\n\n function replaceArrow(delta, dimension, isHorizontal) {\n var $arrow = findElement('.tooltip-arrow, .arrow', tipElement[0]);\n\n $arrow.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')\n .css(isHorizontal ? 'top' : 'left', '');\n }\n\n function destroyTipElement() {\n // Cancel pending callbacks\n clearTimeout(timeout);\n\n if($tooltip.$isShown && tipElement !== null) {\n if(options.autoClose) {\n unbindAutoCloseEvents();\n }\n\n if(options.keyboard) {\n unbindKeyboardEvents();\n }\n }\n\n if(tipScope) {\n tipScope.$destroy();\n tipScope = null;\n }\n\n if(tipElement) {\n tipElement.remove();\n tipElement = $tooltip.$element = null;\n }\n }\n\n return $tooltip;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return TooltipFactory;\n\n };\n\n })\n\n .directive('bsTooltip', function($window, $location, $sce, $tooltip, $$rAF) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Observe scope attributes for change\n attr.$observe('title', function(newValue) {\n if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n var oldValue = scope.title;\n scope.title = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }\n });\n\n // Support scope as an object\n attr.bsTooltip && scope.$watch(attr.bsTooltip, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.title = newValue;\n }\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n newValue === true ? tooltip.show() : tooltip.hide();\n });\n\n // Enabled binding support\n attr.bsEnabled && scope.$watch(attr.bsEnabled, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n newValue === false ? tooltip.setEnabled(false) : tooltip.setEnabled(true);\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n tooltip.setViewport(newValue);\n });\n\n // Initialize popover\n var tooltip = $tooltip(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(tooltip) tooltip.destroy();\n options = null;\n tooltip = null;\n });\n\n }\n };\n\n });\n\n// Source: typeahead/typeahead.js\nangular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$typeahead', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'typeahead',\n prefixEvent: '$typeahead',\n placement: 'bottom-left',\n template: 'typeahead/typeahead.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n minLength: 1,\n filter: 'filter',\n limit: 6,\n autoSelect: false,\n comparator: '',\n trimValue: true\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n\n function TypeaheadFactory(element, controller, config) {\n\n var $typeahead = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $typeahead = $tooltip(element, options);\n var parentScope = config.scope;\n var scope = $typeahead.$scope;\n\n scope.$resetMatches = function(){\n scope.$matches = [];\n scope.$activeIndex = options.autoSelect ? 0 : -1; // If set to 0, the first match will be highlighted\n };\n scope.$resetMatches();\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $typeahead.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $typeahead.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $typeahead.$isVisible();\n };\n\n // Public methods\n\n $typeahead.update = function(matches) {\n scope.$matches = matches;\n if(scope.$activeIndex >= matches.length) {\n scope.$activeIndex = options.autoSelect ? 0: -1;\n }\n\n // When the placement is not one of the bottom placements, re-calc the positioning\n // so the results render correctly.\n if (/^(bottom|bottom-left|bottom-right)$/.test(options.placement)) return;\n\n // wrap in a $timeout so the results are updated\n // before repositioning\n $timeout($typeahead.$applyPlacement);\n };\n\n $typeahead.activate = function(index) {\n scope.$activeIndex = index;\n };\n\n $typeahead.select = function(index) {\n if(index === -1) return;\n var value = scope.$matches[index].value;\n // console.log('$setViewValue', value);\n controller.$setViewValue(value);\n controller.$render();\n scope.$resetMatches();\n if(parentScope) parentScope.$digest();\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $typeahead);\n };\n\n // Protected methods\n\n $typeahead.$isVisible = function() {\n if(!options.minLength || !controller) {\n return !!scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength;\n };\n\n $typeahead.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $typeahead.$onMouseDown = function(evt) {\n // Prevent blur on mousedown\n evt.preventDefault();\n evt.stopPropagation();\n };\n\n $typeahead.$onKeyDown = function(evt) {\n if(!/(38|40|13)/.test(evt.keyCode)) return;\n\n // Let ngSubmit pass if the typeahead tip is hidden or no option is selected\n if($typeahead.$isVisible() && !(evt.keyCode === 13 && scope.$activeIndex === -1)) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n // Select with enter\n if(evt.keyCode === 13 && scope.$matches.length) {\n $typeahead.select(scope.$activeIndex);\n }\n\n // Navigate with keyboard\n else if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n };\n\n // Overrides\n\n var show = $typeahead.show;\n $typeahead.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $typeahead.$onKeyDown);\n }\n }, 0, false);\n };\n\n var hide = $typeahead.hide;\n $typeahead.hide = function() {\n $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $typeahead.$onKeyDown);\n }\n if(!options.autoSelect)\n $typeahead.activate(-1);\n hide();\n };\n\n return $typeahead;\n\n }\n\n TypeaheadFactory.defaults = defaults;\n return TypeaheadFactory;\n\n };\n\n })\n\n .directive('bsTypeahead', function($window, $parse, $q, $typeahead, $parseOptions) {\n\n var defaults = $typeahead.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'filter', 'limit', 'minLength', 'watchOptions', 'selectMode', 'autoSelect', 'comparator', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'trimValue'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n });\n\n // Disable browser autocompletion\n element.attr('autocomplete' ,'off');\n\n // Build proper bsOptions\n var filter = options.filter || defaults.filter;\n var limit = options.limit || defaults.limit;\n var comparator = options.comparator || defaults.comparator;\n\n var bsOptions = attr.bsOptions;\n if(filter) bsOptions += ' | ' + filter + ':$viewValue';\n if (comparator) bsOptions += ':' + comparator;\n if(limit) bsOptions += ' | limitTo:' + limit;\n var parsedOptions = $parseOptions(bsOptions);\n\n // Initialize typeahead\n var typeahead = $typeahead(element, controller, options);\n\n // Watch options on demand\n if(options.watchOptions) {\n // Watch bsOptions values before filtering for changes, drop function calls\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n scope.$watchCollection(watchedOptions, function (newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller).then(function (values) {\n typeahead.update(values);\n controller.$render();\n });\n });\n }\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('$watch', element.attr('ng-model'), newValue);\n scope.$modelValue = newValue; // Publish modelValue on scope for custom templates\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n // Prevent input with no future prospect if selectMode is truthy\n // @TODO test selectMode\n if(options.selectMode && !values.length && newValue.length > 0) {\n controller.$setViewValue(controller.$viewValue.substring(0, controller.$viewValue.length - 1));\n return;\n }\n if(values.length > limit) values = values.slice(0, limit);\n var isVisible = typeahead.$isVisible();\n isVisible && typeahead.update(values);\n // Do not re-queue an update if a correct value has been selected\n if(values.length === 1 && values[0].value === newValue) return;\n !isVisible && typeahead.update(values);\n // Queue a new rendering that will leverage collection loading\n controller.$render();\n });\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var displayValue = parsedOptions.displayValue(modelValue);\n return displayValue === undefined ? '' : displayValue;\n });\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n if(controller.$isEmpty(controller.$viewValue)) return element.val('');\n var index = typeahead.$getIndex(controller.$modelValue);\n var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;\n selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;\n var value = selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '') : '';\n element.val(options.trimValue === false ? value : value.trim());\n };\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (typeahead) typeahead.destroy();\n options = null;\n typeahead = null;\n });\n\n }\n };\n\n });\n\n})(window, document);\n","'use strict';\n\nangular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mgcrea.ngStrap.helpers.debounce'])\n\n .provider('$affix', function() {\n\n var defaults = this.defaults = {\n offsetTop: 'auto',\n inlineStyles: true\n };\n\n this.$get = function($window, debounce, dimensions) {\n\n var bodyEl = angular.element($window.document.body);\n var windowEl = angular.element($window);\n\n function AffixFactory(element, config) {\n\n var $affix = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var targetEl = options.target;\n\n // Initial private vars\n var reset = 'affix affix-top affix-bottom',\n setWidth = false,\n initialAffixTop = 0,\n initialOffsetTop = 0,\n offsetTop = 0,\n offsetBottom = 0,\n affixed = null,\n unpin = null;\n\n var parent = element.parent();\n // Options: custom parent\n if (options.offsetParent) {\n if (options.offsetParent.match(/^\\d+$/)) {\n for (var i = 0; i < (options.offsetParent * 1) - 1; i++) {\n parent = parent.parent();\n }\n }\n else {\n parent = angular.element(options.offsetParent);\n }\n }\n\n $affix.init = function() {\n\n this.$parseOffsets();\n initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n setWidth = !element[0].style.width;\n\n // Bind events\n targetEl.on('scroll', this.checkPosition);\n targetEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', this.$debouncedOnResize);\n\n // Both of these checkPosition() calls are necessary for the case where\n // the user hits refresh after scrolling to the bottom of the page.\n this.checkPosition();\n this.checkPositionWithEventLoop();\n\n };\n\n $affix.destroy = function() {\n\n // Unbind events\n targetEl.off('scroll', this.checkPosition);\n targetEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', this.$debouncedOnResize);\n\n };\n\n $affix.checkPositionWithEventLoop = function() {\n\n // IE 9 throws an error if we use 'this' instead of '$affix'\n // in this setTimeout call\n setTimeout($affix.checkPosition, 1);\n\n };\n\n $affix.checkPosition = function() {\n // if (!this.$element.is(':visible')) return\n\n var scrollTop = getScrollTop();\n var position = dimensions.offset(element[0]);\n var elementHeight = dimensions.height(element[0]);\n\n // Get required affix class according to position\n var affix = getRequiredAffixClass(unpin, position, elementHeight);\n\n // Did affix status changed this last check?\n if(affixed === affix) return;\n affixed = affix;\n\n // Add proper affix class\n element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\n\n if(affix === 'top') {\n unpin = null;\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', '');\n }\n } else if(affix === 'bottom') {\n if (options.offsetUnpin) {\n unpin = -(options.offsetUnpin * 1);\n }\n else {\n // Calculate unpin threshold when affixed to bottom.\n // Hopefully the browser scrolls pixel by pixel.\n unpin = position.top - scrollTop;\n }\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n }\n } else { // affix === 'middle'\n unpin = null;\n if(setWidth) {\n element.css('width', element[0].offsetWidth + 'px');\n }\n if (options.inlineStyles) {\n element.css('position', 'fixed');\n element.css('top', initialAffixTop + 'px');\n }\n }\n\n };\n\n $affix.$onResize = function() {\n $affix.$parseOffsets();\n $affix.checkPosition();\n };\n $affix.$debouncedOnResize = debounce($affix.$onResize, 50);\n\n $affix.$parseOffsets = function() {\n var initialPosition = element.css('position');\n // Reset position to calculate correct offsetTop\n if (options.inlineStyles){\n element.css('position', (options.offsetParent) ? '' : 'relative');\n }\n\n if(options.offsetTop) {\n if(options.offsetTop === 'auto') {\n options.offsetTop = '+0';\n }\n if(options.offsetTop.match(/^[-+]\\d+$/)) {\n initialAffixTop = - options.offsetTop * 1;\n if(options.offsetParent) {\n offsetTop = dimensions.offset(parent[0]).top + (options.offsetTop * 1);\n }\n else {\n offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\n }\n }\n else {\n offsetTop = options.offsetTop * 1;\n }\n }\n\n if(options.offsetBottom) {\n if(options.offsetParent && options.offsetBottom.match(/^[-+]\\d+$/)) {\n // add 1 pixel due to rounding problems...\n offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + (options.offsetBottom * 1) + 1;\n }\n else {\n offsetBottom = options.offsetBottom * 1;\n }\n }\n\n // Bring back the element's position after calculations\n if (options.inlineStyles){\n element.css('position', initialPosition);\n }\n };\n\n // Private methods\n\n function getRequiredAffixClass(unpin, position, elementHeight) {\n\n var scrollTop = getScrollTop();\n var scrollHeight = getScrollHeight();\n\n if(scrollTop <= offsetTop) {\n return 'top';\n } else if(unpin !== null && (scrollTop + unpin <= position.top)) {\n return 'middle';\n } else if(offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n return 'bottom';\n } else {\n return 'middle';\n }\n\n }\n\n function getScrollTop() {\n return targetEl[0] === $window ? $window.pageYOffset : targetEl[0].scrollTop;\n }\n\n function getScrollHeight() {\n return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight;\n }\n\n $affix.init();\n return $affix;\n\n }\n\n return AffixFactory;\n\n };\n\n })\n\n .directive('bsAffix', function($affix, $window) {\n\n return {\n restrict: 'EAC',\n require: '^?bsAffixTarget',\n link: function postLink(scope, element, attr, affixTarget) {\n\n var options = {scope: scope, target: affixTarget ? affixTarget.$element : angular.element($window)};\n angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin', 'inlineStyles'], function(key) {\n if(angular.isDefined(attr[key])) {\n var option = attr[key];\n if (/true/i.test(option)) option = true;\n if (/false/i.test(option)) option = false;\n options[key] = option;\n }\n });\n\n var affix = $affix(element, options);\n scope.$on('$destroy', function() {\n affix && affix.destroy();\n options = null;\n affix = null;\n });\n\n }\n };\n\n })\n\n .directive('bsAffixTarget', function() {\n return {\n controller: function($element) {\n this.$element = $element;\n }\n };\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.button', [])\n\n .provider('$button', function() {\n\n var defaults = this.defaults = {\n activeClass:'active',\n toggleEvent:'click'\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsCheckboxGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"checkbox\"]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.attr('bs-checkbox', '');\n childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));\n });\n }\n\n };\n\n })\n\n .directive('bsCheckbox', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support label > input[type=\"checkbox\"]\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;\n if(constantValueRegExp.test(attr.trueValue)) {\n trueValue = scope.$eval(attr.trueValue);\n }\n var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;\n if(constantValueRegExp.test(attr.falseValue)) {\n falseValue = scope.$eval(attr.falseValue);\n }\n\n // Parse exotic values\n var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';\n if(hasExoticValues) {\n controller.$parsers.push(function(viewValue) {\n // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue);\n return viewValue ? trueValue : falseValue;\n });\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n return angular.equals(modelValue, trueValue);\n });\n // Fix rendering for exotic values\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n controller.$render();\n });\n }\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, trueValue);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n if(!isInput) {\n controller.$setViewValue(!activeElement.hasClass('active'));\n }\n if(!hasExoticValues) {\n controller.$render();\n }\n });\n });\n\n }\n\n };\n\n })\n\n .directive('bsRadioGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"radio\"]');\n angular.forEach(children, function(child) {\n angular.element(child).attr('bs-radio', '');\n angular.element(child).attr('ng-model', attr.ngModel);\n });\n }\n\n };\n\n })\n\n .directive('bsRadio', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support `label > input[type=\"radio\"]` markup\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var value;\n attr.$observe('value', function(v) {\n value = constantValueRegExp.test(v) ? scope.$eval(v) : v;\n controller.$render();\n });\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, value);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n controller.$setViewValue(value);\n controller.$render();\n });\n });\n\n }\n\n };\n\n });\n","'use strict';\n\n// @BUG: following snippet won't compile correctly\n// @TODO: submit issue to core\n// '<span ng-if=\"title\"><strong ng-bind=\"title\"></strong>&nbsp;</span><span ng-bind-html=\"content\"></span>' +\n\nangular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal'])\n\n .provider('$alert', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'alert',\n prefixEvent: 'alert',\n placement: null,\n template: 'alert/alert.tpl.html',\n container: false,\n element: null,\n backdrop: false,\n keyboard: true,\n show: true,\n // Specific options\n duration: false,\n type: false,\n dismissable: true\n };\n\n this.$get = function($modal, $timeout) {\n\n function AlertFactory(config) {\n\n var $alert = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $alert = $modal(options);\n\n // Support scope as string options [/*title, content, */ type, dismissable]\n $alert.$scope.dismissable = !!options.dismissable;\n if(options.type) {\n $alert.$scope.type = options.type;\n }\n\n // Support auto-close duration\n var show = $alert.show;\n if(options.duration) {\n $alert.show = function() {\n show();\n $timeout(function() {\n $alert.hide();\n }, options.duration * 1000);\n };\n }\n\n return $alert;\n\n }\n\n return AlertFactory;\n\n };\n\n })\n\n .directive('bsAlert', function($window, $sce, $alert) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'placement', 'keyboard', 'html', 'container', 'animation', 'duration', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['keyboard', 'html', 'container', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content', 'type'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAlert && scope.$watch(attr.bsAlert, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize alert\n var alert = $alert(options);\n\n // Trigger\n element.on(attr.trigger || 'click', alert.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (alert) alert.destroy();\n options = null;\n alert = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal'])\n\n .provider('$aside', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade-and-slide-right',\n prefixClass: 'aside',\n prefixEvent: 'aside',\n placement: 'right',\n template: 'aside/aside.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($modal) {\n\n function AsideFactory(config) {\n\n var $aside = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $aside = $modal(options);\n\n return $aside;\n\n }\n\n return AsideFactory;\n\n };\n\n })\n\n .directive('bsAside', function($window, $sce, $aside) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAside && scope.$watch(attr.bsAside, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize aside\n var aside = $aside(options);\n\n // Trigger\n element.on(attr.trigger || 'click', aside.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (aside) aside.destroy();\n options = null;\n aside = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.collapse', [])\n\n .provider('$collapse', function() {\n\n var defaults = this.defaults = {\n animation: 'am-collapse',\n disallowToggle: false,\n activeClass: 'in',\n startCollapsed: false,\n allowMultiple: false\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['disallowToggle', 'startCollapsed', 'allowMultiple'], function(key) {\n if(angular.isDefined($attrs[key]) && falseValueRegExp.test($attrs[key]))\n self.$options[key] = false;\n });\n\n self.$toggles = [];\n self.$targets = [];\n\n self.$viewChangeListeners = [];\n\n self.$registerToggle = function(element) {\n self.$toggles.push(element);\n };\n self.$registerTarget = function(element) {\n self.$targets.push(element);\n };\n\n self.$unregisterToggle = function(element) {\n var index = self.$toggles.indexOf(element);\n // remove toggle from $toggles array\n self.$toggles.splice(index, 1);\n };\n self.$unregisterTarget = function(element) {\n var index = self.$targets.indexOf(element);\n\n // remove element from $targets array\n self.$targets.splice(index, 1);\n\n if (self.$options.allowMultiple) {\n // remove target index from $active array values\n deactivateItem(element);\n }\n\n // fix active item indexes\n fixActiveItemIndexes(index);\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n // use array to store all the currently open panels\n self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n self.$setActive = $scope.$setActive = function(value) {\n if(angular.isArray(value)) {\n self.$targets.$active = value;\n }\n else if(!self.$options.disallowToggle) {\n // toogle element active status\n isActive(value) ? deactivateItem(value) : activateItem(value);\n } else {\n activateItem(value);\n }\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$activeIndexes = function() {\n return self.$options.allowMultiple ? self.$targets.$active :\n self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n };\n\n function fixActiveItemIndexes(index) {\n // item with index was removed, so we\n // need to adjust other items index values\n var activeIndexes = self.$targets.$active;\n for(var i = 0; i < activeIndexes.length; i++) {\n if (index < activeIndexes[i]) {\n activeIndexes[i] = activeIndexes[i] - 1;\n }\n\n // the last item is active, so we need to\n // adjust its index\n if (activeIndexes[i] === self.$targets.length) {\n activeIndexes[i] = self.$targets.length - 1;\n }\n }\n }\n\n function isActive(value) {\n var activeItems = self.$targets.$active;\n return activeItems.indexOf(value) === -1 ? false : true;\n }\n\n function deactivateItem(value) {\n var index = self.$targets.$active.indexOf(value);\n if (index !== -1) {\n self.$targets.$active.splice(index, 1);\n }\n }\n\n function activateItem(value) {\n if (!self.$options.allowMultiple) {\n // remove current selected item\n self.$targets.$active.splice(0, 1);\n }\n\n if (self.$targets.$active.indexOf(value) === -1) {\n self.$targets.$active.push(value);\n }\n }\n\n };\n\n this.$get = function() {\n var $collapse = {};\n $collapse.defaults = defaults;\n $collapse.controller = controller;\n return $collapse;\n };\n\n })\n\n .directive('bsCollapse', function($window, $animate, $collapse) {\n\n var defaults = $collapse.defaults;\n\n return {\n require: ['?ngModel', 'bsCollapse'],\n controller: ['$scope', '$element', '$attrs', $collapse.controller],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n if (angular.isArray(modelValue)) {\n // model value is an array, so just replace\n // the active items directly\n bsCollapseCtrl.$setActive(modelValue);\n }\n else {\n var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n if (angular.isArray(activeIndexes)) {\n // we have an array of selected indexes\n if (activeIndexes.indexOf(modelValue * 1) === -1) {\n // item with modelValue index is not active\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n else if (activeIndexes !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n return modelValue;\n });\n\n }\n\n }\n };\n\n })\n\n .directive('bsCollapseToggle', function() {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base attr\n element.attr('data-toggle', 'collapse');\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerToggle(element);\n\n // remove toggle from collapse controller when toggle is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterToggle(element);\n });\n\n element.on('click', function() {\n var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n bsCollapseCtrl.$setActive(index * 1);\n scope.$apply();\n });\n\n }\n };\n\n })\n\n .directive('bsCollapseTarget', function($animate) {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n // scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base class\n element.addClass('collapse');\n\n // Add animation class\n if(bsCollapseCtrl.$options.animation) {\n element.addClass(bsCollapseCtrl.$options.animation);\n }\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerTarget(element);\n\n // remove pane target from collapse controller when target is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterTarget(element);\n });\n\n function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$activeIndexes();\n var action = 'removeClass';\n if (angular.isArray(active)) {\n if (active.indexOf(index) !== -1) {\n action = 'addClass';\n }\n }\n else if (index === active) {\n action = 'addClass';\n }\n\n $animate[action](element, bsCollapseCtrl.$options.activeClass);\n }\n\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.datepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$datepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'datepicker',\n prefixClass: 'datepicker',\n placement: 'bottom-left',\n template: 'datepicker/datepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: false,\n dateType: 'date',\n dateFormat: 'shortDate',\n timezone: null,\n modelDateFormat: null,\n dayFormat: 'dd',\n monthFormat: 'MMM',\n yearFormat: 'yyyy',\n monthTitleFormat: 'MMMM yyyy',\n yearTitleFormat: 'yyyy',\n strictFormat: false,\n autoclose: false,\n minDate: -Infinity,\n maxDate: +Infinity,\n startView: 0,\n minView: 0,\n startWeek: 0,\n daysOfWeekDisabled: '',\n iconLeft: 'glyphicon glyphicon-chevron-left',\n iconRight: 'glyphicon glyphicon-chevron-right'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function DatepickerFactory(element, controller, config) {\n\n var $datepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $datepicker.$options;\n var scope = $datepicker.$scope;\n if(options.startView) options.startView -= options.minView;\n\n // View vars\n\n var pickerViews = datepickerViews($datepicker);\n $datepicker.$views = pickerViews.views;\n var viewDate = pickerViews.viewDate;\n scope.$mode = options.startView;\n scope.$iconLeft = options.iconLeft;\n scope.$iconRight = options.iconRight;\n var $picker = $datepicker.$views[scope.$mode];\n\n // Scope methods\n\n scope.$select = function(date) {\n $datepicker.select(date);\n };\n scope.$selectPane = function(value) {\n $datepicker.$selectPane(value);\n };\n scope.$toggleMode = function() {\n $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);\n };\n\n // Public methods\n\n $datepicker.update = function(date) {\n // console.warn('$datepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $datepicker.$date = date;\n $picker.update.call($picker, date);\n }\n // Build only if pristine\n $datepicker.$build(true);\n };\n\n $datepicker.updateDisabledDates = function(dateRanges) {\n options.disabledDateRanges = dateRanges;\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);\n }\n };\n\n $datepicker.select = function(date, keep) {\n // console.warn('$datepicker.select', date, scope.$mode);\n if(!angular.isDate(controller.$dateValue)) controller.$dateValue = new Date(date);\n if(!scope.$mode || keep) {\n controller.$setViewValue(angular.copy(date));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $datepicker.hide(true); });\n }\n } else {\n angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});\n $datepicker.setMode(scope.$mode - 1);\n $datepicker.$build();\n }\n };\n\n $datepicker.setMode = function(mode) {\n // console.warn('$datepicker.setMode', mode);\n scope.$mode = mode;\n $picker = $datepicker.$views[scope.$mode];\n $datepicker.$build();\n };\n\n // Protected methods\n\n $datepicker.$build = function(pristine) {\n // console.warn('$datepicker.$build() viewDate=%o', viewDate);\n if(pristine === true && $picker.built) return;\n if(pristine === false && !$picker.built) return;\n $picker.build.call($picker);\n };\n\n $datepicker.$updateSelected = function() {\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], updateSelected);\n }\n };\n\n $datepicker.$isSelected = function(date) {\n return $picker.isSelected(date);\n };\n\n $datepicker.$setDisabledEl = function(el) {\n el.disabled = $picker.isDisabled(el.date);\n };\n\n $datepicker.$selectPane = function(value) {\n var steps = $picker.steps;\n // set targetDate to first day of month to avoid problems with\n // date values rollover. This assumes the viewDate does not\n // depend on the day of the month\n var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));\n angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});\n $datepicker.$build();\n };\n\n $datepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $datepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n if(evt.keyCode === 13) {\n if(!scope.$mode) {\n return $datepicker.hide(true);\n } else {\n return scope.$apply(function() { $datepicker.setMode(scope.$mode - 1); });\n }\n }\n\n // Navigate with keyboard\n $picker.onKeyDown(evt);\n parentScope.$digest();\n };\n\n // Private\n\n function updateSelected(el) {\n el.selected = $datepicker.$isSelected(el.date);\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $datepicker.init;\n $datepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'date');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $datepicker.destroy;\n $datepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $datepicker.show;\n $datepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // if $datepicker is no longer showing, don't setup events\n if(!$datepicker.$isShown) return;\n $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $datepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $datepicker.hide;\n $datepicker.hide = function(blur) {\n if(!$datepicker.$isShown) return;\n $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $datepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $datepicker;\n\n }\n\n DatepickerFactory.defaults = defaults;\n return DatepickerFactory;\n\n };\n\n })\n\n .directive('bsDatepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {\n\n var defaults = $datepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'timezone', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!datepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);\n newValue === true ? datepicker.show() : datepicker.hide();\n });\n\n // Initialize datepicker\n var datepicker = $datepicker(element, controller, options);\n options = datepicker.$options;\n // Set expected iOS format\n if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';\n\n var lang = options.lang;\n\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n // Observe attributes for changes\n angular.forEach(['minDate', 'maxDate'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n // console.warn('attr.$observe(%s)=%o', key, newValue);\n datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);\n // Build only if dirty\n !isNaN(datepicker.$options[key]) && datepicker.$build(false);\n validateAgainstMinMaxDate(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n datepicker.update(controller.$dateValue);\n }, true);\n\n // Normalize undefined/null/empty array,\n // so that we don't treat changing from undefined->null as a change.\n function normalizeDateRanges(ranges) {\n if (!ranges || !ranges.length) return null;\n return ranges;\n }\n\n if (angular.isDefined(attr.disabledDates)) {\n scope.$watch(attr.disabledDates, function(disabledRanges, previousValue) {\n disabledRanges = normalizeDateRanges(disabledRanges);\n previousValue = normalizeDateRanges(previousValue);\n\n if (disabledRanges) {\n datepicker.updateDisabledDates(disabledRanges);\n }\n });\n }\n\n function validateAgainstMinMaxDate(parsedDate) {\n if (!angular.isDate(parsedDate)) return;\n var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;\n var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(isValid) controller.$dateValue = parsedDate;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n controller.$setValidity('date', true);\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n return null;\n }\n var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedDate || isNaN(parsedDate.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxDate(parsedDate);\n }\n\n if(options.dateType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedDate, options.timezone, true);\n return formatDate(date, options.modelDateFormat || options.dateFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.dateType === 'number') {\n return date.getTime();\n } else if(options.dateType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.dateType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.dateType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelDateFormat);\n } else if(options.dateType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) {\n // var today = new Date();\n // date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n // }\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getDateFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getDateFormattedString());\n };\n\n function getDateFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(datepicker) datepicker.destroy();\n options = null;\n datepicker = null;\n });\n\n }\n };\n\n })\n\n .provider('datepickerViews', function() {\n\n var defaults = this.defaults = {\n dayFormat: 'dd',\n daySplit: 7\n };\n\n // Split array into smaller arrays\n function split(arr, size) {\n var arrays = [];\n while(arr.length > 0) {\n arrays.push(arr.splice(0, size));\n }\n return arrays;\n }\n\n // Modulus operator\n function mod(n, m) {\n return ((n % m) + m) % m;\n }\n\n this.$get = function($dateFormatter, $dateParser, $sce) {\n\n return function(picker) {\n\n var scope = picker.$scope;\n var options = picker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n var weekDaysLabelsHtml = $sce.trustAsHtml('<th class=\"dow text-center\">' + weekDaysLabels.join('</th><th class=\"dow text-center\">') + '</th>');\n\n var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n\n var views = [{\n format: options.dayFormat,\n split: 7,\n steps: { month: 1 },\n update: function(date, force) {\n if(!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getDate() !== viewDate.date || date.getDate() === 1) {\n // chaging picker current month will cause viewDate.date to be set to first day of the month,\n // in $datepicker.$selectPane, so picker would not update selected day display if\n // user picks first day of the new month.\n // As a workaround, we are always forcing update when picked date is first day of month.\n viewDate.date = picker.$date.getDate();\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5), firstDateOffset = firstDate.getTimezoneOffset();\n var today = dateParser.timezoneOffsetAdjust(new Date(), options.timezone).toDateString();\n // Handle daylight time switch\n if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);\n var days = [], day;\n for(var i = 0; i < 42; i++) { // < 7 * 6\n day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));\n days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n }\n scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);\n scope.showLabels = true;\n scope.labels = weekDaysLabelsHtml;\n scope.rows = split(days, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();\n },\n isDisabled: function(date) {\n var time = date.getTime();\n\n // Disabled because of min/max date.\n if (time < options.minDate || time > options.maxDate) return true;\n\n // Disabled due to being a disabled day of the week\n if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;\n\n // Disabled because of disabled date range.\n if (options.disabledDateRanges) {\n for (var i = 0; i < options.disabledDateRanges.length; i++) {\n if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {\n return true;\n }\n }\n }\n\n return false;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualTime = picker.$date.getTime();\n var newDate;\n\n if(evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);\n else if(evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);\n else if(evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);\n else if(evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'month',\n format: options.monthFormat,\n split: 4,\n steps: { year: 1 },\n update: function(date, force) {\n if(!this.built || date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstMonth = new Date(viewDate.year, 0, 1);\n var months = [], month;\n for (var i = 0; i < 12; i++) {\n month = new Date(viewDate.year, i, 1);\n months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n }\n scope.title = formatDate(month, options.yearTitleFormat);\n scope.showLabels = false;\n scope.rows = split(months, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualMonth = picker.$date.getMonth();\n var newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setMonth(actualMonth - 1);\n else if(evt.keyCode === 38) newDate.setMonth(actualMonth - 4);\n else if(evt.keyCode === 39) newDate.setMonth(actualMonth + 1);\n else if(evt.keyCode === 40) newDate.setMonth(actualMonth + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'year',\n format: options.yearFormat,\n split: 4,\n steps: { year: 12 },\n update: function(date, force) {\n if(!this.built || force || parseInt(date.getFullYear()/20, 10) !== parseInt(viewDate.year/20, 10)) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstYear = viewDate.year - viewDate.year % (this.split * 3);\n var years = [], year;\n for (var i = 0; i < 12; i++) {\n year = new Date(firstYear + i, 0, 1);\n years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});\n }\n scope.title = years[0].label + '-' + years[years.length - 1].label;\n scope.showLabels = false;\n scope.rows = split(years, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear() + 1, 0, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualYear = picker.$date.getFullYear(),\n newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setYear(actualYear - 1);\n else if(evt.keyCode === 38) newDate.setYear(actualYear - 4);\n else if(evt.keyCode === 39) newDate.setYear(actualYear + 1);\n else if(evt.keyCode === 40) newDate.setYear(actualYear + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }];\n\n return {\n views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,\n viewDate: viewDate\n };\n\n };\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$dropdown', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'dropdown',\n prefixEvent: 'dropdown',\n placement: 'bottom-left',\n template: 'dropdown/dropdown.tpl.html',\n trigger: 'click',\n container: false,\n keyboard: true,\n html: false,\n delay: 0\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;\n\n function DropdownFactory(element, config) {\n\n var $dropdown = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n $dropdown = $tooltip(element, options);\n var parentEl = element.parent();\n\n // Protected methods\n\n $dropdown.$onKeyDown = function(evt) {\n if (!/(38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Retrieve focused index\n var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));\n if(!items.length) return;\n var index;\n angular.forEach(items, function(el, i) {\n if(matchesSelector && matchesSelector.call(el, ':focus')) index = i;\n });\n\n // Navigate with keyboard\n if(evt.keyCode === 38 && index > 0) index--;\n else if(evt.keyCode === 40 && index < items.length - 1) index++;\n else if(angular.isUndefined(index)) index = 0;\n items.eq(index)[0].focus();\n\n };\n\n // Overrides\n\n var show = $dropdown.show;\n $dropdown.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n bodyEl.on('click', onBodyClick);\n }, 0, false);\n parentEl.hasClass('dropdown') && parentEl.addClass('open');\n };\n\n var hide = $dropdown.hide;\n $dropdown.hide = function() {\n if(!$dropdown.$isShown) return;\n options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n bodyEl.off('click', onBodyClick);\n parentEl.hasClass('dropdown') && parentEl.removeClass('open');\n hide();\n };\n\n var destroy = $dropdown.destroy;\n $dropdown.destroy = function() {\n bodyEl.off('click', onBodyClick);\n destroy();\n };\n\n // Private functions\n\n function onBodyClick(evt) {\n if(evt.target === element[0]) return;\n return evt.target !== element[0] && $dropdown.hide();\n }\n\n return $dropdown;\n\n }\n\n return DropdownFactory;\n\n };\n\n })\n\n .directive('bsDropdown', function($window, $sce, $dropdown) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as an object\n attr.bsDropdown && scope.$watch(attr.bsDropdown, function(newValue, oldValue) {\n scope.content = newValue;\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!dropdown || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(dropdown),?/i);\n newValue === true ? dropdown.show() : dropdown.hide();\n });\n\n // Initialize dropdown\n var dropdown = $dropdown(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (dropdown) dropdown.destroy();\n options = null;\n dropdown = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dateFormatter', [])\n\n .service('$dateFormatter', function($locale, dateFilter) {\n\n // The unused `lang` arguments are on purpose. The default implementation does not\n // use them and it always uses the locale loaded into the `$locale` service.\n // Custom implementations might use it, thus allowing different directives to\n // have different languages.\n\n this.getDefaultLocale = function() {\n return $locale.id;\n };\n\n // Format is either a data format name, e.g. \"shortTime\" or \"fullDate\", or a date format\n // Return either the corresponding date format or the given date format.\n this.getDatetimeFormat = function(format, lang) {\n return $locale.DATETIME_FORMATS[format] || format;\n };\n\n this.weekdaysShort = function(lang) {\n return $locale.DATETIME_FORMATS.SHORTDAY;\n };\n\n function splitTimeFormat(format) {\n return /(h+)([:\\.])?(m+)([:\\.])?(s*)[ ]?(a?)/i.exec(format).slice(1);\n }\n\n // h:mm a => h\n this.hoursFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[0];\n };\n\n // h:mm a => mm\n this.minutesFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[2];\n };\n\n // h:mm:ss a => ss\n this.secondsFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => :\n this.timeSeparator = function(timeFormat) {\n return splitTimeFormat(timeFormat)[1];\n };\n\n // h:mm:ss a => true, h:mm a => false\n this.showSeconds = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => true, H.mm => false\n this.showAM = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[5];\n };\n\n this.formatDate = function(date, format, lang, timezone){\n return dateFilter(date, format, timezone);\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dateParser', [])\n\n.provider('$dateParser', function($localeProvider) {\n\n // define a custom ParseDate object to use instead of native Date\n // to avoid date values wrapping when setting date component values\n function ParseDate() {\n this.year = 1970;\n this.month = 0;\n this.day = 1;\n this.hours = 0;\n this.minutes = 0;\n this.seconds = 0;\n this.milliseconds = 0;\n }\n\n ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };\n ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };\n ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };\n ParseDate.prototype.setHours = function(value) { this.hours = value; };\n ParseDate.prototype.getHours = function() { return this.hours; };\n ParseDate.prototype.setDate = function(value) { this.day = value; };\n ParseDate.prototype.setMonth = function(value) { this.month = value; };\n ParseDate.prototype.setFullYear = function(value) { this.year = value; };\n ParseDate.prototype.fromDate = function(value) {\n this.year = value.getFullYear();\n this.month = value.getMonth();\n this.day = value.getDate();\n this.hours = value.getHours();\n this.minutes = value.getMinutes();\n this.seconds = value.getSeconds();\n this.milliseconds = value.getMilliseconds();\n return this;\n };\n\n ParseDate.prototype.toDate = function() {\n return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n };\n\n var proto = ParseDate.prototype;\n\n function noop() {\n }\n\n function isNumeric(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n function indexOfCaseInsensitive(array, value) {\n var len = array.length, str=value.toString().toLowerCase();\n for (var i=0; i<len; i++) {\n if (array[i].toLowerCase() === str) { return i; }\n }\n return -1; // Return -1 per the \"Array.indexOf()\" method.\n }\n\n var defaults = this.defaults = {\n format: 'shortDate',\n strict: false\n };\n\n this.$get = function($locale, dateFilter) {\n\n var DateParserFactory = function(config) {\n\n var options = angular.extend({}, defaults, config);\n\n var $dateParser = {};\n\n var regExpMap = {\n 'sss' : '[0-9]{3}',\n 'ss' : '[0-5][0-9]',\n 's' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n 'mm' : '[0-5][0-9]',\n 'm' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n 'HH' : '[01][0-9]|2[0-3]',\n 'H' : options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]',\n 'hh' : '[0][1-9]|[1][012]',\n 'h' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n 'a' : 'AM|PM',\n 'EEEE' : $locale.DATETIME_FORMATS.DAY.join('|'),\n 'EEE' : $locale.DATETIME_FORMATS.SHORTDAY.join('|'),\n 'dd' : '0[1-9]|[12][0-9]|3[01]',\n 'd' : options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]',\n 'MMMM' : $locale.DATETIME_FORMATS.MONTH.join('|'),\n 'MMM' : $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n 'MM' : '0[1-9]|1[012]',\n 'M' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n 'yyyy' : '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',\n 'yy' : '[0-9]{2}',\n 'y' : options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}',\n };\n\n var setFnMap = {\n 'sss' : proto.setMilliseconds,\n 'ss' : proto.setSeconds,\n 's' : proto.setSeconds,\n 'mm' : proto.setMinutes,\n 'm' : proto.setMinutes,\n 'HH' : proto.setHours,\n 'H' : proto.setHours,\n 'hh' : proto.setHours,\n 'h' : proto.setHours,\n 'EEEE' : noop,\n 'EEE' : noop,\n 'dd' : proto.setDate,\n 'd' : proto.setDate,\n 'a' : function(value) { var hours = this.getHours() % 12; return this.setHours(value.match(/pm/i) ? hours + 12 : hours); },\n 'MMMM' : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.MONTH, value)); },\n 'MMM' : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.SHORTMONTH, value)); },\n 'MM' : function(value) { return this.setMonth(1 * value - 1); },\n 'M' : function(value) { return this.setMonth(1 * value - 1); },\n 'yyyy' : proto.setFullYear,\n 'yy' : function(value) { return this.setFullYear(2000 + 1 * value); },\n 'y' : proto.setFullYear\n };\n\n var regex, setMap;\n\n $dateParser.init = function() {\n $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;\n regex = regExpForFormat($dateParser.$format);\n setMap = setMapForFormat($dateParser.$format);\n };\n\n $dateParser.isValid = function(date) {\n if(angular.isDate(date)) return !isNaN(date.getTime());\n return regex.test(date);\n };\n\n $dateParser.parse = function(value, baseDate, format, timezone) {\n // check for date format special names\n if(format) format = $locale.DATETIME_FORMATS[format] || format;\n if(angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format, timezone);\n var formatRegex = format ? regExpForFormat(format) : regex;\n var formatSetMap = format ? setMapForFormat(format) : setMap;\n var matches = formatRegex.exec(value);\n if(!matches) return false;\n // use custom ParseDate object to set parsed values\n var date = baseDate && !isNaN(baseDate.getTime()) ? new ParseDate().fromDate(baseDate) : new ParseDate().fromDate(new Date(1970, 0, 1, 0));\n for(var i = 0; i < matches.length - 1; i++) {\n formatSetMap[i] && formatSetMap[i].call(date, matches[i+1]);\n }\n // convert back to native Date object\n var newDate = date.toDate();\n\n // check new native Date object for day values overflow\n if (parseInt(date.day, 10) !== newDate.getDate()) {\n return false;\n }\n\n return newDate;\n };\n\n $dateParser.getDateForAttribute = function(key, value) {\n var date;\n\n if(value === 'today') {\n var today = new Date();\n date = new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, (key === 'minDate' ? 0 : -1));\n } else if(angular.isString(value) && value.match(/^\".+\"$/)) { // Support {{ dateObj }}\n date = new Date(value.substr(1, value.length - 2));\n } else if(isNumeric(value)) {\n date = new Date(parseInt(value, 10));\n } else if (angular.isString(value) && 0 === value.length) { // Reset date\n date = key === 'minDate' ? -Infinity : +Infinity;\n } else {\n date = new Date(value);\n }\n\n return date;\n };\n\n $dateParser.getTimeForAttribute = function(key, value) {\n var time;\n\n if(value === 'now') {\n time = new Date().setFullYear(1970, 0, 1);\n } else if(angular.isString(value) && value.match(/^\".+\"$/)) {\n time = new Date(value.substr(1, value.length - 2)).setFullYear(1970, 0, 1);\n } else if(isNumeric(value)) {\n time = new Date(parseInt(value, 10)).setFullYear(1970, 0, 1);\n } else if (angular.isString(value) && 0 === value.length) { // Reset time\n time = key === 'minTime' ? -Infinity : +Infinity;\n } else {\n time = $dateParser.parse(value, new Date(1970, 0, 1, 0));\n }\n\n return time;\n };\n\n /* Handle switch to/from daylight saving.\n * Hours may be non-zero on daylight saving cut-over:\n * > 12 when midnight changeover, but then cannot generate\n * midnight datetime, so jump to 1AM, otherwise reset.\n * @param date (Date) the date to check\n * @return (Date) the corrected date\n *\n * __ copied from jquery ui datepicker __\n */\n $dateParser.daylightSavingAdjust = function(date) {\n if (!date) {\n return null;\n }\n date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n return date;\n };\n\n /* Correct the date for timezone offset.\n * @param date (Date) the date to adjust\n * @param timezone (string) the timezone to adjust for\n * @param undo (boolean) to add or subtract timezone offset\n * @return (Date) the corrected date\n */\n $dateParser.timezoneOffsetAdjust = function(date, timezone, undo) {\n if (!date) {\n return null;\n }\n // Right now, only 'UTC' is supported.\n if (timezone && timezone === 'UTC') {\n date = new Date(date.getTime());\n date.setMinutes(date.getMinutes() + (undo?-1:1)*date.getTimezoneOffset());\n }\n return date;\n };\n\n // Private functions\n\n function setMapForFormat(format) {\n var keys = Object.keys(setFnMap), i;\n var map = [], sortedMap = [];\n // Map to setFn\n var clonedFormat = format;\n for(i = 0; i < keys.length; i++) {\n if(format.split(keys[i]).length > 1) {\n var index = clonedFormat.search(keys[i]);\n format = format.split(keys[i]).join('');\n if(setFnMap[keys[i]]) {\n map[index] = setFnMap[keys[i]];\n }\n }\n }\n // Sort result map\n angular.forEach(map, function(v) {\n // conditional required since angular.forEach broke around v1.2.21\n // related pr: https://github.com/angular/angular.js/pull/8525\n if(v) sortedMap.push(v);\n });\n return sortedMap;\n }\n\n function escapeReservedSymbols(text) {\n return text.replace(/\\//g, '[\\\\/]').replace('/-/g', '[-]').replace(/\\./g, '[.]').replace(/\\\\s/g, '[\\\\s]');\n }\n\n function regExpForFormat(format) {\n var keys = Object.keys(regExpMap), i;\n\n var re = format;\n // Abstract replaces to avoid collisions\n for(i = 0; i < keys.length; i++) {\n re = re.split(keys[i]).join('${' + i + '}');\n }\n // Replace abstracted values\n for(i = 0; i < keys.length; i++) {\n re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');\n }\n format = escapeReservedSymbols(format);\n\n return new RegExp('^' + re + '$', ['i']);\n }\n\n $dateParser.init();\n return $dateParser;\n\n };\n\n return DateParserFactory;\n\n };\n\n});\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.debounce', [])\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L693\n.factory('debounce', function($timeout) {\n return function(func, wait, immediate) {\n var timeout = null;\n return function() {\n var context = this,\n args = arguments,\n callNow = immediate && !timeout;\n if(timeout) {\n $timeout.cancel(timeout);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(!immediate) {\n func.apply(context, args);\n }\n }, wait, false);\n if(callNow) {\n func.apply(context, args);\n }\n return timeout;\n };\n };\n})\n\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L661\n.factory('throttle', function($timeout) {\n return function(func, wait, options) {\n var timeout = null;\n options || (options = {});\n return function() {\n var context = this,\n args = arguments;\n if(!timeout) {\n if(options.leading !== false) {\n func.apply(context, args);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(options.trailing !== false) {\n func.apply(context, args);\n }\n }, wait, false);\n }\n };\n };\n});\n\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n .factory('dimensions', function($document, $window) {\n\n var jqLite = angular.element;\n var fn = {};\n\n /**\n * Test the element nodeName\n * @param element\n * @param name\n */\n var nodeName = fn.nodeName = function(element, name) {\n return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();\n };\n\n /**\n * Returns the element computed style\n * @param element\n * @param prop\n * @param extra\n */\n fn.css = function(element, prop, extra) {\n var value;\n if (element.currentStyle) { //IE\n value = element.currentStyle[prop];\n } else if (window.getComputedStyle) {\n value = window.getComputedStyle(element)[prop];\n } else {\n value = element.style[prop];\n }\n return extra === true ? parseFloat(value) || 0 : value;\n };\n\n /**\n * Provides read-only equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.offset = function(element) {\n var boxRect = element.getBoundingClientRect();\n var docElement = element.ownerDocument;\n return {\n width: boxRect.width || element.offsetWidth,\n height: boxRect.height || element.offsetHeight,\n top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),\n left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)\n };\n };\n \n /**\n * Provides set equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip\n * @url http://api.jquery.com/offset/\n * @param element\n * @param options\n * @param i\n */\n fn.setOffset = function (element, options, i) {\n var curPosition,\n curLeft,\n curCSSTop,\n curTop,\n curOffset,\n curCSSLeft,\n calculatePosition,\n position = fn.css(element, 'position'),\n curElem = angular.element(element),\n props = {};\n \n // Set position first, in-case top/left are set even on static elem\n if (position === 'static') {\n element.style.position = 'relative';\n }\n \n curOffset = fn.offset(element);\n curCSSTop = fn.css(element, 'top');\n curCSSLeft = fn.css(element, 'left');\n calculatePosition = (position === 'absolute' || position === 'fixed') && \n (curCSSTop + curCSSLeft).indexOf('auto') > -1;\n \n // Need to be able to calculate position if either\n // top or left is auto and position is either absolute or fixed\n if (calculatePosition) {\n curPosition = fn.position(element);\n curTop = curPosition.top;\n curLeft = curPosition.left;\n } else {\n curTop = parseFloat(curCSSTop) || 0;\n curLeft = parseFloat(curCSSLeft) || 0;\n }\n \n if (angular.isFunction(options)) {\n options = options.call(element, i, curOffset);\n }\n \n if (options.top !== null ) {\n props.top = (options.top - curOffset.top) + curTop;\n }\n if ( options.left !== null ) {\n props.left = (options.left - curOffset.left) + curLeft;\n }\n\n if ('using' in options) {\n options.using.call(curElem, props);\n } else {\n curElem.css({\n top: props.top + 'px',\n left: props.left + 'px'\n });\n }\n };\n\n /**\n * Provides read-only equivalent of jQuery's position function\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.position = function(element) {\n\n var offsetParentRect = {top: 0, left: 0},\n offsetParentElement,\n offset;\n\n // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n if (fn.css(element, 'position') === 'fixed') {\n\n // We assume that getBoundingClientRect is available when computed position is fixed\n offset = element.getBoundingClientRect();\n\n } else {\n\n // Get *real* offsetParentElement\n offsetParentElement = offsetParent(element);\n\n // Get correct offsets\n offset = fn.offset(element);\n if (!nodeName(offsetParentElement, 'html')) {\n offsetParentRect = fn.offset(offsetParentElement);\n }\n\n // Add offsetParent borders\n offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);\n offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);\n }\n\n // Subtract parent offsets and element margins\n return {\n width: element.offsetWidth,\n height: element.offsetHeight,\n top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),\n left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)\n };\n\n };\n\n /**\n * Returns the closest, non-statically positioned offsetParent of a given element\n * @required-by fn.position\n * @param element\n */\n var offsetParent = function offsetParentElement(element) {\n var docElement = element.ownerDocument;\n var offsetParent = element.offsetParent || docElement;\n if(nodeName(offsetParent, '#document')) return docElement.documentElement;\n while(offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {\n offsetParent = offsetParent.offsetParent;\n }\n return offsetParent || docElement.documentElement;\n };\n\n /**\n * Provides equivalent of jQuery's height function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/height/\n * @param element\n * @param outer\n */\n fn.height = function(element, outer) {\n var value = element.offsetHeight;\n if(outer) {\n value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);\n } else {\n value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);\n }\n return value;\n };\n\n /**\n * Provides equivalent of jQuery's width function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/width/\n * @param element\n * @param outer\n */\n fn.width = function(element, outer) {\n var value = element.offsetWidth;\n if(outer) {\n value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);\n } else {\n value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);\n }\n return value;\n };\n\n return fn;\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.parseOptions', [])\n\n .provider('$parseOptions', function() {\n\n var defaults = this.defaults = {\n 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+(.*?))?$/\n };\n\n this.$get = function($parse, $q) {\n\n function ParseOptionsFactory(attr, config) {\n\n var $parseOptions = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n $parseOptions.$values = [];\n\n // Private vars\n var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;\n\n $parseOptions.init = function() {\n $parseOptions.$match = match = attr.match(options.regexp);\n displayFn = $parse(match[2] || match[1]),\n valueName = match[4] || match[6],\n keyName = match[5],\n groupByFn = $parse(match[3] || ''),\n valueFn = $parse(match[2] ? match[1] : valueName),\n valuesFn = $parse(match[7]);\n };\n\n $parseOptions.valuesFn = function(scope, controller) {\n return $q.when(valuesFn(scope, controller))\n .then(function(values) {\n $parseOptions.$values = values ? parseValues(values, scope) : {};\n return $parseOptions.$values;\n });\n };\n\n $parseOptions.displayValue = function(modelValue) {\n var scope = {};\n scope[valueName] = modelValue;\n return displayFn(scope);\n };\n\n // Private functions\n\n function parseValues(values, scope) {\n return values.map(function(match, index) {\n var locals = {}, label, value;\n locals[valueName] = match;\n label = displayFn(scope, locals);\n value = valueFn(scope, locals);\n return {label: label, value: value, index: index};\n });\n }\n\n $parseOptions.init();\n return $parseOptions;\n\n }\n\n return ParseOptionsFactory;\n\n };\n\n });\n","'use strict';\n\n(angular.version.minor < 3 && angular.version.dot < 14) && angular.module('ng')\n\n.factory('$$rAF', function($window, $timeout) {\n\n var requestAnimationFrame = $window.requestAnimationFrame ||\n $window.webkitRequestAnimationFrame ||\n $window.mozRequestAnimationFrame;\n\n var cancelAnimationFrame = $window.cancelAnimationFrame ||\n $window.webkitCancelAnimationFrame ||\n $window.mozCancelAnimationFrame ||\n $window.webkitCancelRequestAnimationFrame;\n\n var rafSupported = !!requestAnimationFrame;\n var raf = rafSupported ?\n function(fn) {\n var id = requestAnimationFrame(fn);\n return function() {\n cancelAnimationFrame(id);\n };\n } :\n function(fn) {\n var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n return function() {\n $timeout.cancel(timer);\n };\n };\n\n raf.supported = rafSupported;\n\n return raf;\n\n});\n\n// .factory('$$animateReflow', function($$rAF, $document) {\n\n// var bodyEl = $document[0].body;\n\n// return function(fn) {\n// //the returned function acts as the cancellation function\n// return $$rAF(function() {\n// //the line below will force the browser to perform a repaint\n// //so that all the animated elements within the animation frame\n// //will be properly updated and drawn on screen. This is\n// //required to perform multi-class CSS based animations with\n// //Firefox. DO NOT REMOVE THIS LINE.\n// var a = bodyEl.offsetWidth + 1;\n// fn();\n// });\n// };\n\n// });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$modal', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n backdropAnimation: 'am-fade',\n prefixClass: 'modal',\n prefixEvent: 'modal',\n placement: 'top',\n template: 'modal/modal.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {\n\n var forEach = angular.forEach;\n var trim = String.prototype.trim;\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n var bodyElement = angular.element($window.document.body);\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n\n function ModalFactory(config) {\n\n var $modal = {};\n\n // Common vars\n var options = $modal.$options = angular.extend({}, defaults, config);\n $modal.$promise = fetchTemplate(options.template);\n var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(!options.element && !options.container) {\n options.container = 'body';\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $modal.$id = options.id || options.element && options.element.attr('id') || '';\n\n // Support scope as string options\n forEach(['title', 'content'], function(key) {\n if(options[key]) scope[key] = $sce.trustAsHtml(options[key]);\n });\n\n // Provide scope helpers\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $modal.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $modal.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $modal.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $modal.$isShown = scope.$isShown = false;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $modal.$promise = $modal.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);\n // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n if(!config.template) contentEl.next().remove();\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize modal\n var modalLinker, modalElement;\n var backdropElement = angular.element('<div class=\"' + options.prefixClass + '-backdrop\"/>');\n backdropElement.css({position:'fixed', top:'0px', left:'0px', bottom:'0px', right:'0px', 'z-index': 1038});\n $modal.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n modalLinker = $compile(template);\n $modal.init();\n });\n\n $modal.init = function() {\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n $modal.show();\n });\n }\n\n };\n\n $modal.destroy = function() {\n\n // Remove element\n if(modalElement) {\n modalElement.remove();\n modalElement = null;\n }\n if(backdropElement) {\n backdropElement.remove();\n backdropElement = null;\n }\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $modal.show = function() {\n if($modal.$isShown) return;\n\n var parent, after;\n if(angular.isElement(options.container)) {\n parent = options.container;\n after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;\n } else {\n if (options.container) {\n parent = findElement(options.container);\n after = parent[0] && parent[0].lastChild ? angular.element(parent[0].lastChild) : null;\n } else {\n parent = null;\n after = options.element;\n }\n }\n\n // Fetch a cloned element linked from template\n modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\n\n if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n return;\n }\n\n // Set the initial positioning.\n modalElement.css({display: 'block'}).addClass(options.placement);\n\n // Options: animation\n if(options.animation) {\n if(options.backdrop) {\n backdropElement.addClass(options.backdropAnimation);\n }\n modalElement.addClass(options.animation);\n }\n\n if(options.backdrop) {\n $animate.enter(backdropElement, bodyElement, null);\n }\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.enter(modalElement, parent, after, enterAnimateCallback);\n if(promise && promise.then) promise.then(enterAnimateCallback);\n\n $modal.$isShown = scope.$isShown = true;\n safeDigest(scope);\n // Focus once the enter-animation has started\n // Weird PhantomJS bug hack\n var el = modalElement[0];\n requestAnimationFrame(function() {\n el.focus();\n });\n\n bodyElement.addClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n }\n\n // Bind events\n if(options.backdrop) {\n modalElement.on('click', hideOnBackdropClick);\n backdropElement.on('click', hideOnBackdropClick);\n backdropElement.on('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.on('keyup', $modal.$onKeyUp);\n }\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $modal);\n }\n\n $modal.hide = function() {\n if(!$modal.$isShown) return;\n\n if(scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {\n return;\n }\n var promise = $animate.leave(modalElement, leaveAnimateCallback);\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n if(options.backdrop) {\n $animate.leave(backdropElement);\n }\n $modal.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.backdrop) {\n modalElement.off('click', hideOnBackdropClick);\n backdropElement.off('click', hideOnBackdropClick);\n backdropElement.off('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.off('keyup', $modal.$onKeyUp);\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $modal);\n bodyElement.removeClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n }\n }\n\n $modal.toggle = function() {\n\n $modal.$isShown ? $modal.hide() : $modal.show();\n\n };\n\n $modal.focus = function() {\n modalElement[0].focus();\n };\n\n // Protected methods\n\n $modal.$onKeyUp = function(evt) {\n\n if (evt.which === 27 && $modal.$isShown) {\n $modal.hide();\n evt.stopPropagation();\n }\n\n };\n\n // Private methods\n\n function hideOnBackdropClick(evt) {\n if(evt.target !== evt.currentTarget) return;\n options.backdrop === 'static' ? $modal.focus() : $modal.hide();\n }\n\n function preventEventDefault(evt) {\n evt.preventDefault();\n }\n\n return $modal;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return ModalFactory;\n\n };\n\n })\n\n .directive('bsModal', function($window, $sce, $modal) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsModal && scope.$watch(attr.bsModal, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize modal\n var modal = $modal(options);\n\n // Trigger\n element.on(attr.trigger || 'click', modal.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (modal) modal.destroy();\n options = null;\n modal = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.navbar', [])\n\n .provider('$navbar', function() {\n\n var defaults = this.defaults = {\n activeClass: 'active',\n routeAttr: 'data-match-route',\n strict: false\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsNavbar', function($window, $location, $navbar) {\n\n var defaults = $navbar.defaults;\n\n return {\n restrict: 'A',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = angular.copy(defaults);\n angular.forEach(Object.keys(defaults), function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Watch for the $location\n scope.$watch(function() {\n\n return $location.path();\n\n }, function(newValue, oldValue) {\n\n var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');\n\n angular.forEach(liElements, function(li) {\n\n var liElement = angular.element(li);\n var pattern = liElement.attr(options.routeAttr).replace('/', '\\\\/');\n if(options.strict) {\n pattern = '^' + pattern + '$';\n }\n var regexp = new RegExp(pattern, 'i');\n\n if(regexp.test(newValue)) {\n liElement.addClass(options.activeClass);\n } else {\n liElement.removeClass(options.activeClass);\n }\n\n });\n\n });\n\n }\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$popover', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n // uncommenting the next two lines will break backwards compatability\n // prefixClass: 'popover',\n // prefixEvent: 'popover',\n container: false,\n target: false,\n placement: 'right',\n template: 'popover/popover.tpl.html',\n contentTemplate: false,\n trigger: 'click',\n keyboard: true,\n html: false,\n title: '',\n content: '',\n delay: 0,\n autoClose: false\n };\n\n this.$get = function($tooltip) {\n\n function PopoverFactory(element, config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n var $popover = $tooltip(element, options);\n\n // Support scope as string options [/*title, */content]\n if(options.content) {\n $popover.$scope.content = options.content;\n }\n\n return $popover;\n\n }\n\n return PopoverFactory;\n\n };\n\n })\n\n .directive('bsPopover', function($window, $sce, $popover) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'customClass', 'autoClose', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoClose'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n });\n });\n\n // Support scope as an object\n attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);\n newValue === true ? popover.show() : popover.hide();\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n popover.setViewport(newValue);\n });\n\n // Initialize popover\n var popover = $popover(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (popover) popover.destroy();\n options = null;\n popover = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', 'mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$scrollspy', function() {\n\n // Pool of registered spies\n var spies = this.$$spies = {};\n\n var defaults = this.defaults = {\n debounce: 150,\n throttle: 100,\n offset: 100\n };\n\n this.$get = function($window, $document, $rootScope, dimensions, debounce, throttle) {\n\n var windowEl = angular.element($window);\n var docEl = angular.element($document.prop('documentElement'));\n var bodyEl = angular.element($window.document.body);\n\n // Helper functions\n\n function nodeName(element, name) {\n return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();\n }\n\n function ScrollSpyFactory(config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n if(!options.element) options.element = bodyEl;\n var isWindowSpy = nodeName(options.element, 'body');\n var scrollEl = isWindowSpy ? windowEl : options.element;\n var scrollId = isWindowSpy ? 'window' : options.id;\n\n // Use existing spy\n if(spies[scrollId]) {\n spies[scrollId].$$count++;\n return spies[scrollId];\n }\n\n var $scrollspy = {};\n\n // Private vars\n var unbindViewContentLoaded, unbindIncludeContentLoaded;\n var trackedElements = $scrollspy.$trackedElements = [];\n var sortedElements = [];\n var activeTarget;\n var debouncedCheckPosition;\n var throttledCheckPosition;\n var debouncedCheckOffsets;\n var viewportHeight;\n var scrollTop;\n\n $scrollspy.init = function() {\n\n // Setup internal ref counter\n this.$$count = 1;\n\n // Bind events\n debouncedCheckPosition = debounce(this.checkPosition, options.debounce);\n throttledCheckPosition = throttle(this.checkPosition, options.throttle);\n scrollEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', debouncedCheckPosition);\n scrollEl.on('scroll', throttledCheckPosition);\n\n debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);\n unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);\n unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);\n debouncedCheckOffsets();\n\n // Register spy for reuse\n if(scrollId) {\n spies[scrollId] = $scrollspy;\n }\n\n };\n\n $scrollspy.destroy = function() {\n\n // Check internal ref counter\n this.$$count--;\n if(this.$$count > 0) {\n return;\n }\n\n // Unbind events\n scrollEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', debouncedCheckPosition);\n scrollEl.off('scroll', throttledCheckPosition);\n unbindViewContentLoaded();\n unbindIncludeContentLoaded();\n if (scrollId) {\n delete spies[scrollId];\n }\n };\n\n $scrollspy.checkPosition = function() {\n\n // Not ready yet\n if(!sortedElements.length) return;\n\n // Calculate the scroll position\n scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;\n\n // Calculate the viewport height for use by the components\n viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));\n\n // Activate first element if scroll is smaller\n if(scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {\n return $scrollspy.$activateElement(sortedElements[0]);\n }\n\n // Activate proper element\n for (var i = sortedElements.length; i--;) {\n if(angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) continue;\n if(activeTarget === sortedElements[i].target) continue;\n if(scrollTop < sortedElements[i].offsetTop) continue;\n if(sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) continue;\n return $scrollspy.$activateElement(sortedElements[i]);\n }\n\n };\n\n $scrollspy.checkPositionWithEventLoop = function() {\n // IE 9 throws an error if we use 'this' instead of '$scrollspy'\n // in this setTimeout call\n setTimeout($scrollspy.checkPosition, 1);\n };\n\n // Protected methods\n\n $scrollspy.$activateElement = function(element) {\n if(activeTarget) {\n var activeElement = $scrollspy.$getTrackedElement(activeTarget);\n if(activeElement) {\n activeElement.source.removeClass('active');\n if(nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {\n activeElement.source.parent().parent().removeClass('active');\n }\n }\n }\n activeTarget = element.target;\n element.source.addClass('active');\n if(nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {\n element.source.parent().parent().addClass('active');\n }\n };\n\n $scrollspy.$getTrackedElement = function(target) {\n return trackedElements.filter(function(obj) {\n return obj.target === target;\n })[0];\n };\n\n // Track offsets behavior\n\n $scrollspy.checkOffsets = function() {\n\n angular.forEach(trackedElements, function(trackedElement) {\n var targetElement = document.querySelector(trackedElement.target);\n trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;\n if(options.offset && trackedElement.offsetTop !== null) trackedElement.offsetTop -= options.offset * 1;\n });\n\n sortedElements = trackedElements\n .filter(function(el) {\n return el.offsetTop !== null;\n })\n .sort(function(a, b) {\n return a.offsetTop - b.offsetTop;\n });\n\n debouncedCheckPosition();\n\n };\n\n $scrollspy.trackElement = function(target, source) {\n trackedElements.push({target: target, source: source});\n };\n\n $scrollspy.untrackElement = function(target, source) {\n var toDelete;\n for (var i = trackedElements.length; i--;) {\n if(trackedElements[i].target === target && trackedElements[i].source === source) {\n toDelete = i;\n break;\n }\n }\n trackedElements = trackedElements.splice(toDelete, 1);\n };\n\n $scrollspy.activate = function(i) {\n trackedElements[i].addClass('active');\n };\n\n // Initialize plugin\n\n $scrollspy.init();\n return $scrollspy;\n\n }\n\n return ScrollSpyFactory;\n\n };\n\n })\n\n .directive('bsScrollspy', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'EAC',\n link: function postLink(scope, element, attr) {\n\n var options = {scope: scope};\n angular.forEach(['offset', 'target'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n var scrollspy = $scrollspy(options);\n scrollspy.trackElement(options.target, element);\n\n scope.$on('$destroy', function() {\n if (scrollspy) {\n scrollspy.untrackElement(options.target, element);\n scrollspy.destroy();\n }\n options = null;\n scrollspy = null;\n });\n\n }\n };\n\n })\n\n\n .directive('bsScrollspyList', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'A',\n compile: function postLink(element, attr) {\n var children = element[0].querySelectorAll('li > a[href]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));\n });\n }\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$select', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'select',\n prefixEvent: '$select',\n placement: 'bottom-left',\n template: 'select/select.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n multiple: false,\n allNoneButtons: false,\n sort: true,\n caretHtml: '&nbsp;<span class=\"caret\"></span>',\n placeholder: 'Choose among the following...',\n allText: 'All',\n noneText: 'None',\n maxLength: 3,\n maxLengthHtml: 'selected',\n iconCheckmark: 'glyphicon glyphicon-ok'\n };\n\n this.$get = function($window, $document, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n\n function SelectFactory(element, controller, config) {\n\n var $select = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $select = $tooltip(element, options);\n var scope = $select.$scope;\n\n scope.$matches = [];\n if (options.multiple) {\n scope.$activeIndex = [];\n }\n else {\n scope.$activeIndex = -1;\n }\n scope.$isMultiple = options.multiple;\n scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n scope.$iconCheckmark = options.iconCheckmark;\n scope.$allText = options.allText;\n scope.$noneText = options.noneText;\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $select.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $select.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $select.$isVisible();\n };\n\n scope.$isActive = function(index) {\n return $select.$isActive(index);\n };\n\n scope.$selectAll = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (!scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n scope.$selectNone = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n // Public methods\n\n $select.update = function(matches) {\n scope.$matches = matches;\n $select.$updateActiveIndex();\n };\n\n $select.activate = function(index) {\n if(options.multiple) {\n $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);\n if(options.sort) scope.$activeIndex.sort();\n } else {\n scope.$activeIndex = index;\n }\n return scope.$activeIndex;\n };\n\n $select.select = function(index) {\n var value = scope.$matches[index].value;\n scope.$apply(function() {\n $select.activate(index);\n if(options.multiple) {\n controller.$setViewValue(scope.$activeIndex.map(function(index) {\n return scope.$matches[index].value;\n }));\n } else {\n controller.$setViewValue(value);\n // Hide if single select\n $select.hide();\n }\n });\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $select);\n };\n\n // Protected methods\n\n $select.$updateActiveIndex = function() {\n if(controller.$modelValue && scope.$matches.length) {\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n scope.$activeIndex = controller.$modelValue.map(function(value) {\n return $select.$getIndex(value);\n });\n } else {\n scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n }\n } else if(scope.$activeIndex >= scope.$matches.length) {\n scope.$activeIndex = options.multiple ? [] : 0;\n }\n };\n\n $select.$isVisible = function() {\n if(!options.minLength || !controller) {\n return scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && controller.$viewValue.length >= options.minLength;\n };\n\n $select.$isActive = function(index) {\n if(options.multiple) {\n return scope.$activeIndex.indexOf(index) !== -1;\n } else {\n return scope.$activeIndex === index;\n }\n };\n\n $select.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $select.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n targetEl.triggerHandler('click');\n }\n };\n\n $select.$onKeyDown = function(evt) {\n if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // release focus on tab\n if (options.multiple && evt.keyCode === 9) {\n return $select.hide();\n }\n\n // Select with enter\n if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n return $select.select(scope.$activeIndex);\n }\n\n if (!options.multiple) {\n // Navigate with keyboard\n if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 38 && scope.$activeIndex < 0) scope.$activeIndex = scope.$matches.length - 1;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n }\n };\n\n // Overrides\n\n var _show = $select.show;\n $select.show = function() {\n _show();\n if(options.multiple) {\n $select.$element.addClass('select-multiple');\n }\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $select.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $select.hide;\n $select.hide = function() {\n if(!options.multiple && !controller.$modelValue) {\n scope.$activeIndex = -1;\n }\n $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $select.$onKeyDown);\n }\n _hide(true);\n };\n\n return $select;\n\n }\n\n SelectFactory.defaults = defaults;\n return SelectFactory;\n\n };\n\n })\n\n .directive('bsSelect', function($window, $parse, $q, $select, $parseOptions) {\n\n var defaults = $select.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, placeholder: defaults.placeholder};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'placeholder', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id', 'sort', 'caretHtml', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'allNoneButtons', 'sort'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Only parse data-multiple. Angular sets existence attributes to true (multiple/required/etc), they apply this\n // to data-multiple as well for some reason, so we'll parse this ourselves and disregard multiple\n var dataMultiple = element.attr('data-multiple');\n if(angular.isDefined(dataMultiple)) {\n if(falseValueRegExp.test(dataMultiple))\n options.multiple = false;\n else\n options.multiple = dataMultiple;\n }\n\n // Add support for select markup\n if(element[0].nodeName.toLowerCase() === 'select') {\n var inputEl = element;\n inputEl.css('display', 'none');\n element = angular.element('<button type=\"button\" class=\"btn btn-default\"></button>');\n inputEl.after(element);\n }\n\n // Build proper bsOptions\n var parsedOptions = $parseOptions(attr.bsOptions);\n\n // Initialize select\n var select = $select(element, controller, options);\n\n // Watch bsOptions values before filtering for changes\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n scope.$watchCollection(watchedOptions, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n select.update(values);\n controller.$render();\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n select.$updateActiveIndex();\n controller.$render();\n }, true);\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var selected, index;\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n selected = controller.$modelValue.map(function(value) {\n index = select.$getIndex(value);\n return angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }).filter(angular.isDefined);\n if(selected.length > (options.maxLength || defaults.maxLength)) {\n selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml);\n } else {\n selected = selected.join(', ');\n }\n } else {\n index = select.$getIndex(controller.$modelValue);\n selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }\n element.html((selected ? selected : options.placeholder) + (options.caretHtml ? options.caretHtml : defaults.caretHtml));\n };\n\n if(options.multiple){\n controller.$isEmpty = function(value){\n return !value || value.length === 0;\n };\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (select) select.destroy();\n options = null;\n select = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.tab', [])\n\n .provider('$tab', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n template: 'tab/tab.tpl.html',\n navClass: 'nav-tabs',\n activeClass: 'active'\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'navClass', 'activeClass'], function(key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // Publish options on scope\n $scope.$navClass = self.$options.navClass;\n $scope.$activeClass = self.$options.activeClass;\n\n self.$panes = $scope.$panes = [];\n\n // Please use $activePaneChangeListeners if you use `bsActivePane`\n // Because we removed `ngModel` as default, we rename viewChangeListeners to\n // activePaneChangeListeners to make more sense.\n self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n if(angular.isUndefined(self.$panes.$active)) {\n $scope.$setActive(pane.name || 0);\n }\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var active = self.$panes.$active;\n var activeIndex;\n if(angular.isString(active)) {\n activeIndex = self.$panes.map(function(pane) {\n return pane.name;\n }).indexOf(active);\n } else {\n activeIndex = self.$panes.$active;\n }\n\n // remove pane from $panes array\n self.$panes.splice(index, 1);\n\n if (index < activeIndex) {\n // we removed a pane before the active pane, so we need to\n // decrement the active pane index\n activeIndex--;\n }\n else if (index === activeIndex && activeIndex === self.$panes.length) {\n // we remove the active pane and it was the one at the end,\n // so select the previous one\n activeIndex--;\n }\n if(activeIndex >= 0 && activeIndex < self.$panes.length) {\n self.$setActive(self.$panes[activeIndex].name || activeIndex);\n } else {\n self.$setActive();\n }\n };\n\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$activePaneChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$isActive = $scope.$isActive = function($pane, $index) {\n return self.$panes.$active === $pane.name || self.$panes.$active === $index;\n };\n\n };\n\n this.$get = function() {\n var $tab = {};\n $tab.defaults = defaults;\n $tab.controller = controller;\n return $tab;\n };\n\n })\n\n .directive('bsTabs', function($window, $animate, $tab, $parse) {\n\n var defaults = $tab.defaults;\n\n return {\n require: ['?ngModel', 'bsTabs'],\n transclude: true,\n scope: true,\n controller: ['$scope', '$element', '$attrs', $tab.controller],\n templateUrl: function(element, attr) {\n return attr.template || defaults.template;\n },\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // 'ngModel' does interfere with form validation\n // and status, use `bsActivePane` instead to avoid it\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n bsTabsCtrl.$setActive(modelValue);\n return modelValue;\n });\n\n }\n\n if (attrs.bsActivePane) {\n // adapted from angularjs ngModelController bindings\n // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n // Update bsActivePane value with change\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n });\n\n // watch bsActivePane for value changes\n scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n bsTabsCtrl.$setActive(newValue);\n }, true);\n }\n }\n };\n\n })\n\n .directive('bsPane', function($window, $animate, $sce) {\n\n return {\n require: ['^?ngModel', '^bsTabs'],\n scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // Add base class\n element.addClass('tab-pane');\n\n // Observe title attribute for change\n attrs.$observe('title', function(newValue, oldValue) {\n scope.title = $sce.trustAsHtml(newValue);\n });\n\n // Save tab name into scope\n scope.name = attrs.name;\n\n // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\n }\n\n attrs.$observe('disabled', function(newValue, oldValue) {\n scope.disabled = scope.$eval(newValue);\n });\n\n // Push pane to parent bsTabs controller\n bsTabsCtrl.$push(scope);\n\n // remove pane from tab controller when pane is destroyed\n scope.$on('$destroy', function() {\n bsTabsCtrl.$remove(scope);\n });\n\n function render() {\n var index = bsTabsCtrl.$panes.indexOf(scope);\n $animate[bsTabsCtrl.$isActive(scope, index) ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.timepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$timepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'timepicker',\n prefixClass: 'timepicker',\n placement: 'bottom-left',\n template: 'timepicker/timepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: true,\n timeType: 'date',\n timeFormat: 'shortTime',\n timezone: null,\n modelTimeFormat: null,\n autoclose: false,\n minTime: -Infinity,\n maxTime: +Infinity,\n length: 5,\n hourStep: 1,\n minuteStep: 5,\n secondStep: 5,\n roundDisplay: false,\n iconUp: 'glyphicon glyphicon-chevron-up',\n iconDown: 'glyphicon glyphicon-chevron-down',\n arrowBehavior: 'pager'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function timepickerFactory(element, controller, config) {\n\n var $timepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $timepicker.$options;\n var scope = $timepicker.$scope;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n function floorMinutes(time)\n {\n // coeff used to floor current time to nearest minuteStep interval\n var coeff = 1000 * 60 * options.minuteStep;\n return new Date(Math.floor(time.getTime() / coeff) * coeff);\n }\n\n // View vars\n\n var selectedIndex = 0;\n var defaultDate = options.roundDisplay ? floorMinutes(new Date()) : new Date();\n var startDate = controller.$dateValue || defaultDate;\n var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n var hoursFormat = $dateFormatter.hoursFormat(format),\n timeSeparator = $dateFormatter.timeSeparator(format),\n minutesFormat = $dateFormatter.minutesFormat(format),\n secondsFormat = $dateFormatter.secondsFormat(format),\n showSeconds = $dateFormatter.showSeconds(format),\n showAM = $dateFormatter.showAM(format);\n\n scope.$iconUp = options.iconUp;\n scope.$iconDown = options.iconDown;\n\n // Scope methods\n\n scope.$select = function(date, index) {\n $timepicker.select(date, index);\n };\n scope.$moveIndex = function(value, index) {\n $timepicker.$moveIndex(value, index);\n };\n scope.$switchMeridian = function(date) {\n $timepicker.switchMeridian(date);\n };\n\n // Public methods\n\n $timepicker.update = function(date) {\n // console.warn('$timepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $timepicker.$date = date;\n angular.extend(viewDate, {hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds(), millisecond: date.getMilliseconds()});\n $timepicker.$build();\n } else if(!$timepicker.$isBuilt) {\n $timepicker.$build();\n }\n };\n\n $timepicker.select = function(date, index, keep) {\n // console.warn('$timepicker.select', date, scope.$mode);\n if(!controller.$dateValue || isNaN(controller.$dateValue.getTime())) controller.$dateValue = new Date(1970, 0, 1);\n if(!angular.isDate(date)) date = new Date(date);\n if(index === 0) controller.$dateValue.setHours(date.getHours());\n else if(index === 1) controller.$dateValue.setMinutes(date.getMinutes());\n else if(index === 2) controller.$dateValue.setSeconds(date.getSeconds());\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $timepicker.hide(true); });\n }\n };\n\n $timepicker.switchMeridian = function(date) {\n if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) {\n return;\n }\n var hours = (date || controller.$dateValue).getHours();\n controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12);\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n };\n\n // Protected methods\n\n $timepicker.$build = function() {\n // console.warn('$timepicker.$build() viewDate=%o', viewDate);\n var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n var hours = [], hour;\n for(i = 0; i < options.length; i++) {\n hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);\n hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});\n }\n var minutes = [], minute;\n for(i = 0; i < options.length; i++) {\n minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);\n minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n }\n var seconds = [], second;\n for(i = 0; i < options.length; i++) {\n second = new Date(1970, 0, 1, 0, 0, viewDate.second - (midIndex - i) * options.secondStep);\n seconds.push({date: second, label: formatDate(second, secondsFormat), selected: $timepicker.$date && $timepicker.$isSelected(second, 2), disabled: $timepicker.$isDisabled(second, 2)});\n }\n\n var rows = [];\n for(i = 0; i < options.length; i++) {\n if (showSeconds) {\n rows.push([hours[i], minutes[i], seconds[i]]);\n } else {\n rows.push([hours[i], minutes[i]]);\n }\n }\n scope.rows = rows;\n scope.showSeconds = showSeconds;\n scope.showAM = showAM;\n scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n scope.timeSeparator = timeSeparator;\n $timepicker.$isBuilt = true;\n };\n\n $timepicker.$isSelected = function(date, index) {\n if(!$timepicker.$date) return false;\n else if(index === 0) {\n return date.getHours() === $timepicker.$date.getHours();\n } else if(index === 1) {\n return date.getMinutes() === $timepicker.$date.getMinutes();\n } else if(index === 2) {\n return date.getSeconds() === $timepicker.$date.getSeconds();\n }\n };\n\n $timepicker.$isDisabled = function(date, index) {\n var selectedTime;\n if(index === 0) {\n selectedTime = date.getTime() + viewDate.minute * 6e4 + viewDate.second * 1e3;\n } else if(index === 1) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.second * 1e3;\n } else if(index === 2) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.minute * 6e4;\n }\n return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1;\n };\n\n scope.$arrowAction = function (value, index) {\n if (options.arrowBehavior === 'picker') {\n $timepicker.$setTimeByStep(value,index);\n } else {\n $timepicker.$moveIndex(value,index);\n }\n };\n\n $timepicker.$setTimeByStep = function(value, index) {\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n if (index === 0) {\n newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n }\n else if (index === 1) {\n newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\n }\n else if (index === 2) {\n newDate.setSeconds(seconds - (parseInt(options.secondStep, 10) * value));\n }\n $timepicker.select(newDate, index, true);\n };\n\n $timepicker.$moveIndex = function(value, index) {\n var targetDate;\n if(index === 0) {\n targetDate = new Date(1970, 0, 1, viewDate.hour + (value * options.length), viewDate.minute, viewDate.second);\n angular.extend(viewDate, {hour: targetDate.getHours()});\n } else if(index === 1) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + (value * options.length * options.minuteStep), viewDate.second);\n angular.extend(viewDate, {minute: targetDate.getMinutes()});\n } else if(index === 2) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute, viewDate.second + (value * options.length * options.secondStep));\n angular.extend(viewDate, {second: targetDate.getSeconds()});\n }\n $timepicker.$build();\n };\n\n $timepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n if(evt.target.nodeName.toLowerCase() !== 'input') evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $timepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Close on enter\n if(evt.keyCode === 13) return $timepicker.hide(true);\n\n // Navigate with keyboard\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n var sepLength = 1;\n var lateralMove = /(37|39)/.test(evt.keyCode);\n var count = 2 + showSeconds * 1 + showAM * 1;\n\n // Navigate indexes (left, right)\n if (lateralMove) {\n if(evt.keyCode === 37) selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1;\n else if(evt.keyCode === 39) selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0;\n }\n\n // Update values (up, down)\n var selectRange = [0, hoursLength];\n var incr = 0;\n if (evt.keyCode === 38) incr = -1;\n if (evt.keyCode === 40) incr = +1;\n var isSeconds = selectedIndex === 2 && showSeconds;\n var isMeridian = selectedIndex === 2 && !showSeconds || selectedIndex === 3 && showSeconds;\n if(selectedIndex === 0) {\n newDate.setHours(hours + incr*parseInt(options.hourStep, 10));\n // re-calculate hours length because we have changed hours value\n hoursLength = formatDate(newDate, hoursFormat).length;\n selectRange = [0, hoursLength];\n } else if(selectedIndex === 1) {\n newDate.setMinutes(minutes + incr*parseInt(options.minuteStep, 10));\n // re-calculate minutes length because we have changes minutes value\n minutesLength = formatDate(newDate, minutesFormat).length;\n selectRange = [hoursLength + sepLength, minutesLength];\n } else if(isSeconds) {\n newDate.setSeconds(seconds + incr*parseInt(options.secondStep, 10));\n // re-calculate seconds length because we have changes seconds value\n secondsLength = formatDate(newDate, secondsFormat).length;\n selectRange = [hoursLength + sepLength + minutesLength + sepLength, secondsLength];\n } else if(isMeridian) {\n if(!lateralMove) $timepicker.switchMeridian();\n selectRange = [hoursLength + sepLength + minutesLength + sepLength + (secondsLength + sepLength)*showSeconds, 2];\n }\n $timepicker.select(newDate, selectedIndex, true);\n createSelection(selectRange[0], selectRange[1]);\n parentScope.$digest();\n };\n\n // Private\n\n function createSelection(start, length) {\n var end = start + length;\n if(element[0].createTextRange) {\n var selRange = element[0].createTextRange();\n selRange.collapse(true);\n selRange.moveStart('character', start);\n selRange.moveEnd('character', end);\n selRange.select();\n } else if(element[0].setSelectionRange) {\n element[0].setSelectionRange(start, end);\n } else if(angular.isUndefined(element[0].selectionStart)) {\n element[0].selectionStart = start;\n element[0].selectionEnd = end;\n }\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $timepicker.init;\n $timepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'time');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $timepicker.destroy;\n $timepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $timepicker.show;\n $timepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $timepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $timepicker.hide;\n $timepicker.hide = function(blur) {\n if(!$timepicker.$isShown) return;\n $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $timepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $timepicker;\n\n }\n\n timepickerFactory.defaults = defaults;\n return timepickerFactory;\n\n };\n\n })\n\n\n .directive('bsTimepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n var defaults = $timepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'timeType', 'timeFormat', 'timezone', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'secondStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'roundDisplay', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative', 'roundDisplay'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!timepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(timepicker),?/i);\n newValue === true ? timepicker.show() : timepicker.hide();\n });\n\n // Initialize timepicker\n if(isNative && (options.useNative || defaults.useNative)) options.timeFormat = 'HH:mm';\n var timepicker = $timepicker(element, controller, options);\n options = timepicker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n // Initialize parser\n var dateParser = $dateParser({format: options.timeFormat, lang: lang});\n\n // Observe attributes for changes\n angular.forEach(['minTime', 'maxTime'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n !isNaN(timepicker.$options[key]) && timepicker.$build();\n validateAgainstMinMaxTime(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue);\n timepicker.update(controller.$dateValue);\n }, true);\n\n function validateAgainstMinMaxTime(parsedTime) {\n if (!angular.isDate(parsedTime)) return;\n var isMinValid = isNaN(options.minTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) >= options.minTime;\n var isMaxValid = isNaN(options.maxTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) <= options.maxTime;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(!isValid) {\n return;\n }\n controller.$dateValue = parsedTime;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n controller.$setValidity('date', true);\n return null;\n }\n var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedTime || isNaN(parsedTime.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxTime(parsedTime);\n }\n\n if(options.timeType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedTime, options.timezone, true);\n return formatDate(date, options.modelTimeFormat || options.timeFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.timeType === 'number') {\n return date.getTime();\n } else if(options.timeType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.timeType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.timeType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelTimeFormat);\n } else if(options.timeType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5);\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getTimeFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getTimeFormattedString());\n };\n\n function getTimeFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (timepicker) timepicker.destroy();\n options = null;\n timepicker = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$tooltip', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n prefixClass: 'tooltip',\n prefixEvent: 'tooltip',\n container: false,\n target: false,\n placement: 'top',\n template: 'tooltip/tooltip.tpl.html',\n contentTemplate: false,\n trigger: 'hover focus',\n keyboard: false,\n html: false,\n show: false,\n title: '',\n type: '',\n delay: 0,\n autoClose: false,\n bsEnabled: true,\n viewport: {\n selector: 'body',\n padding: 0\n }\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n var trim = String.prototype.trim;\n var isTouch = 'createTouch' in $window.document;\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n var $body = angular.element($window.document);\n\n function TooltipFactory(element, config) {\n\n var $tooltip = {};\n\n // Common vars\n var nodeName = element[0].nodeName.toLowerCase();\n var options = $tooltip.$options = angular.extend({}, defaults, config);\n $tooltip.$promise = fetchTemplate(options.template);\n var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(options.delay && angular.isString(options.delay)) {\n var split = options.delay.split(',').map(parseFloat);\n options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $tooltip.$id = options.id || element.attr('id') || '';\n\n // Support scope as string options\n if(options.title) {\n scope.title = $sce.trustAsHtml(options.title);\n }\n\n // Provide scope helpers\n scope.$setEnabled = function(isEnabled) {\n scope.$$postDigest(function() {\n $tooltip.setEnabled(isEnabled);\n });\n };\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $tooltip.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $tooltip.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $tooltip.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $tooltip.$isShown = scope.$isShown = false;\n\n // Private vars\n var timeout, hoverState;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $tooltip.$promise = $tooltip.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]);\n if(!contentEl.length) contentEl = findElement('[ng-bind=\"title\"]', templateEl[0]);\n contentEl.removeAttr('ng-bind').html(contentTemplate);\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize tooltip\n var tipLinker, tipElement, tipTemplate, tipContainer, tipScope;\n $tooltip.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n tipTemplate = template;\n tipLinker = $compile(template);\n $tooltip.init();\n });\n\n $tooltip.init = function() {\n\n // Options: delay\n if (options.delay && angular.isNumber(options.delay)) {\n options.delay = {\n show: options.delay,\n hide: options.delay\n };\n }\n\n // Replace trigger on touch devices ?\n // if(isTouch && options.trigger === defaults.trigger) {\n // options.trigger.replace(/hover/g, 'click');\n // }\n\n // Options : container\n if(options.container === 'self') {\n tipContainer = element;\n } else if(angular.isElement(options.container)) {\n tipContainer = options.container;\n } else if(options.container) {\n tipContainer = findElement(options.container);\n }\n\n // Options: trigger\n bindTriggerEvents();\n\n // Options: target\n if(options.target) {\n options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n }\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n options.trigger === 'focus' ? element[0].focus() : $tooltip.show();\n });\n }\n\n };\n\n $tooltip.destroy = function() {\n\n // Unbind events\n unbindTriggerEvents();\n\n // Remove element\n destroyTipElement();\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $tooltip.enter = function() {\n\n clearTimeout(timeout);\n hoverState = 'in';\n if (!options.delay || !options.delay.show) {\n return $tooltip.show();\n }\n\n timeout = setTimeout(function() {\n if (hoverState ==='in') $tooltip.show();\n }, options.delay.show);\n\n };\n\n $tooltip.show = function() {\n if (!options.bsEnabled || $tooltip.$isShown) return;\n\n scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n var parent, after;\n if (options.container) {\n parent = tipContainer;\n if (tipContainer[0].lastChild) {\n after = angular.element(tipContainer[0].lastChild);\n } else {\n after = null;\n }\n } else {\n parent = null;\n after = element;\n }\n\n\n // Hide any existing tipElement\n if(tipElement) destroyTipElement();\n // Fetch a cloned element linked from template\n tipScope = $tooltip.$scope.$new();\n tipElement = $tooltip.$element = tipLinker(tipScope, function(clonedElement, scope) {});\n\n // Set the initial positioning. Make the tooltip invisible\n // so IE doesn't try to focus on it off screen.\n tipElement.css({top: '-9999px', left: '-9999px', right: 'auto', display: 'block', visibility: 'hidden'});\n\n // Options: animation\n if(options.animation) tipElement.addClass(options.animation);\n // Options: type\n if(options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n // Options: custom classes\n if(options.customClass) tipElement.addClass(options.customClass);\n\n // Append the element, without any animations. If we append\n // using $animate.enter, some of the animations cause the placement\n // to be off due to the transforms.\n after ? after.after(tipElement) : parent.prepend(tipElement);\n\n $tooltip.$isShown = scope.$isShown = true;\n safeDigest(scope);\n\n // Now, apply placement\n $tooltip.$applyPlacement();\n\n // Once placed, animate it.\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.enter(tipElement, parent, after, enterAnimateCallback);\n if(promise && promise.then) promise.then(enterAnimateCallback);\n safeDigest(scope);\n\n $$rAF(function () {\n // Once the tooltip is placed and the animation starts, make the tooltip visible\n if(tipElement) tipElement.css({visibility: 'visible'});\n });\n\n // Bind events\n if(options.keyboard) {\n if(options.trigger !== 'focus') {\n $tooltip.focus();\n }\n bindKeyboardEvents();\n }\n\n if(options.autoClose) {\n bindAutoCloseEvents();\n }\n\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $tooltip);\n }\n\n $tooltip.leave = function() {\n\n clearTimeout(timeout);\n hoverState = 'out';\n if (!options.delay || !options.delay.hide) {\n return $tooltip.hide();\n }\n timeout = setTimeout(function () {\n if (hoverState === 'out') {\n $tooltip.hide();\n }\n }, options.delay.hide);\n\n };\n\n var _blur;\n var _tipToHide;\n $tooltip.hide = function(blur) {\n\n if(!$tooltip.$isShown) return;\n scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n\n // store blur value for leaveAnimateCallback to use\n _blur = blur;\n\n // store current tipElement reference to use\n // in leaveAnimateCallback\n _tipToHide = tipElement;\n\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.leave(tipElement, leaveAnimateCallback);\n if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n $tooltip.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.keyboard && tipElement !== null) {\n unbindKeyboardEvents();\n }\n\n if(options.autoClose && tipElement !== null) {\n unbindAutoCloseEvents();\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\n\n // check if current tipElement still references\n // the same element when hide was called\n if (tipElement === _tipToHide) {\n // Allow to blur the input when hidden, like when pressing enter key\n if(_blur && options.trigger === 'focus') {\n return element[0].blur();\n }\n\n // clean up child scopes\n destroyTipElement();\n }\n }\n\n $tooltip.toggle = function() {\n $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter();\n };\n\n $tooltip.focus = function() {\n tipElement[0].focus();\n };\n\n $tooltip.setEnabled = function(isEnabled) {\n options.bsEnabled = isEnabled;\n };\n\n $tooltip.setViewport = function(viewport) {\n options.viewport = viewport;\n };\n\n // Protected methods\n\n $tooltip.$applyPlacement = function() {\n if(!tipElement) return;\n\n // Determine if we're doing an auto or normal placement\n var placement = options.placement,\n autoToken = /\\s?auto?\\s?/i,\n autoPlace = autoToken.test(placement);\n\n if (autoPlace) {\n placement = placement.replace(autoToken, '') || defaults.placement;\n }\n\n // Need to add the position class before we get\n // the offsets\n tipElement.addClass(options.placement);\n\n // Get the position of the target element\n // and the height and width of the tooltip so we can center it.\n var elementPosition = getPosition(),\n tipWidth = tipElement.prop('offsetWidth'),\n tipHeight = tipElement.prop('offsetHeight');\n\n // If we're auto placing, we need to check the positioning\n if (autoPlace) {\n var originalPlacement = placement;\n var container = options.container ? findElement(options.container) : element.parent();\n var containerPosition = getPosition(container);\n\n // Determine if the vertical placement\n if (originalPlacement.indexOf('bottom') >= 0 && elementPosition.bottom + tipHeight > containerPosition.bottom) {\n placement = originalPlacement.replace('bottom', 'top');\n } else if (originalPlacement.indexOf('top') >= 0 && elementPosition.top - tipHeight < containerPosition.top) {\n placement = originalPlacement.replace('top', 'bottom');\n }\n\n // Determine the horizontal placement\n // The exotic placements of left and right are opposite of the standard placements. Their arrows are put on the left/right\n // and flow in the opposite direction of their placement.\n if ((originalPlacement === 'right' || originalPlacement === 'bottom-left' || originalPlacement === 'top-left') &&\n elementPosition.right + tipWidth > containerPosition.width) {\n\n placement = originalPlacement === 'right' ? 'left' : placement.replace('left', 'right');\n } else if ((originalPlacement === 'left' || originalPlacement === 'bottom-right' || originalPlacement === 'top-right') &&\n elementPosition.left - tipWidth < containerPosition.left) {\n\n placement = originalPlacement === 'left' ? 'right' : placement.replace('right', 'left');\n }\n\n tipElement.removeClass(originalPlacement).addClass(placement);\n }\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n applyPlacement(tipPosition, placement);\n };\n\n $tooltip.$onKeyUp = function(evt) {\n if (evt.which === 27 && $tooltip.$isShown) {\n $tooltip.hide();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusKeyUp = function(evt) {\n if (evt.which === 27) {\n element[0].blur();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusElementMouseDown = function(evt) {\n evt.preventDefault();\n evt.stopPropagation();\n // Some browsers do not auto-focus buttons (eg. Safari)\n $tooltip.$isShown ? element[0].blur() : element[0].focus();\n };\n\n // bind/unbind events\n function bindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n angular.forEach(triggers, function(trigger) {\n if(trigger === 'click') {\n element.on('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n });\n }\n\n function unbindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n for (var i = triggers.length; i--;) {\n var trigger = triggers[i];\n if(trigger === 'click') {\n element.off('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n }\n }\n\n function bindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.on('keyup', $tooltip.$onKeyUp);\n } else {\n element.on('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n function unbindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.off('keyup', $tooltip.$onKeyUp);\n } else {\n element.off('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n var _autoCloseEventsBinded = false;\n function bindAutoCloseEvents() {\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // Stop propagation when clicking inside tooltip\n tipElement.on('click', stopEventPropagation);\n\n // Hide when clicking outside tooltip\n $body.on('click', $tooltip.hide);\n\n _autoCloseEventsBinded = true;\n }, 0, false);\n }\n\n function unbindAutoCloseEvents() {\n if (_autoCloseEventsBinded) {\n tipElement.off('click', stopEventPropagation);\n $body.off('click', $tooltip.hide);\n _autoCloseEventsBinded = false;\n }\n }\n\n function stopEventPropagation(event) {\n event.stopPropagation();\n }\n\n // Private methods\n\n function getPosition($element) {\n $element = $element || (options.target || element);\n\n var el = $element[0],\n isBody = el.tagName === 'BODY';\n\n var elRect = el.getBoundingClientRect();\n var rect = {};\n\n // IE8 has issues with angular.extend and using elRect directly.\n // By coping the values of elRect into a new object, we can continue to use extend\n for (var p in elRect) {\n // DO NOT use hasOwnProperty when inspecting the return of getBoundingClientRect.\n rect[p] = elRect[p];\n }\n\n if (rect.width === null) {\n // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n rect = angular.extend({}, rect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });\n }\n var elOffset = isBody ? { top: 0, left: 0 } : dimensions.offset(el),\n scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.prop('scrollTop') || 0 },\n outerDims = isBody ? { width: document.documentElement.clientWidth, height: $window.innerHeight } : null;\n\n return angular.extend({}, rect, scroll, outerDims, elOffset);\n }\n\n function getCalculatedOffset(placement, position, actualWidth, actualHeight) {\n var offset;\n var split = placement.split('-');\n\n switch (split[0]) {\n case 'right':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left + position.width\n };\n break;\n case 'bottom':\n offset = {\n top: position.top + position.height,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n case 'left':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left - actualWidth\n };\n break;\n default:\n offset = {\n top: position.top - actualHeight,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n }\n\n if(!split[1]) {\n return offset;\n }\n\n // Add support for corners @todo css\n if(split[0] === 'top' || split[0] === 'bottom') {\n switch (split[1]) {\n case 'left':\n offset.left = position.left;\n break;\n case 'right':\n offset.left = position.left + position.width - actualWidth;\n }\n } else if(split[0] === 'left' || split[0] === 'right') {\n switch (split[1]) {\n case 'top':\n offset.top = position.top - actualHeight;\n break;\n case 'bottom':\n offset.top = position.top + position.height;\n }\n }\n\n return offset;\n }\n\n function applyPlacement(offset, placement) {\n var tip = tipElement[0],\n width = tip.offsetWidth,\n height = tip.offsetHeight;\n\n // manually read margins because getBoundingClientRect includes difference\n var marginTop = parseInt(dimensions.css(tip, 'margin-top'), 10),\n marginLeft = parseInt(dimensions.css(tip, 'margin-left'), 10);\n\n // we must check for NaN for ie 8/9\n if (isNaN(marginTop)) marginTop = 0;\n if (isNaN(marginLeft)) marginLeft = 0;\n\n offset.top = offset.top + marginTop;\n offset.left = offset.left + marginLeft;\n\n // dimensions setOffset doesn't round pixel values\n // so we use setOffset directly with our own function\n dimensions.setOffset(tip, angular.extend({\n using: function (props) {\n tipElement.css({\n top: Math.round(props.top) + 'px',\n left: Math.round(props.left) + 'px',\n right: ''\n });\n }\n }, offset), 0);\n\n // check to see if placing tip in new offset caused the tip to resize itself\n var actualWidth = tip.offsetWidth,\n actualHeight = tip.offsetHeight;\n\n if (placement === 'top' && actualHeight !== height) {\n offset.top = offset.top + height - actualHeight;\n }\n\n // If it's an exotic placement, exit now instead of\n // applying a delta and changing the arrow\n if (/top-left|top-right|bottom-left|bottom-right/.test(placement)) return;\n\n var delta = getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);\n\n if (delta.left) {\n offset.left += delta.left;\n } else {\n offset.top += delta.top;\n }\n\n dimensions.setOffset(tip, offset);\n\n if (/top|right|bottom|left/.test(placement)) {\n var isVertical = /top|bottom/.test(placement),\n arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight,\n arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';\n\n replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical);\n }\n }\n\n function getViewportAdjustedDelta(placement, position, actualWidth, actualHeight) {\n var delta = { top: 0, left: 0 },\n $viewport = options.viewport && findElement(options.viewport.selector || options.viewport);\n\n if (!$viewport) {\n return delta;\n }\n\n var viewportPadding = options.viewport && options.viewport.padding || 0,\n viewportDimensions = getPosition($viewport);\n\n if (/right|left/.test(placement)) {\n var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll,\n bottomEdgeOffset = position.top + viewportPadding - viewportDimensions.scroll + actualHeight;\n if (topEdgeOffset < viewportDimensions.top) { // top overflow\n delta.top = viewportDimensions.top - topEdgeOffset;\n } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;\n }\n } else {\n var leftEdgeOffset = position.left - viewportPadding,\n rightEdgeOffset = position.left + viewportPadding + actualWidth;\n if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n delta.left = viewportDimensions.left - leftEdgeOffset;\n } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow\n delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;\n }\n }\n\n return delta;\n }\n\n function replaceArrow(delta, dimension, isHorizontal) {\n var $arrow = findElement('.tooltip-arrow, .arrow', tipElement[0]);\n\n $arrow.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')\n .css(isHorizontal ? 'top' : 'left', '');\n }\n\n function destroyTipElement() {\n // Cancel pending callbacks\n clearTimeout(timeout);\n\n if($tooltip.$isShown && tipElement !== null) {\n if(options.autoClose) {\n unbindAutoCloseEvents();\n }\n\n if(options.keyboard) {\n unbindKeyboardEvents();\n }\n }\n\n if(tipScope) {\n tipScope.$destroy();\n tipScope = null;\n }\n\n if(tipElement) {\n tipElement.remove();\n tipElement = $tooltip.$element = null;\n }\n }\n\n return $tooltip;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return TooltipFactory;\n\n };\n\n })\n\n .directive('bsTooltip', function($window, $location, $sce, $tooltip, $$rAF) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Observe scope attributes for change\n attr.$observe('title', function(newValue) {\n if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n var oldValue = scope.title;\n scope.title = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }\n });\n\n // Support scope as an object\n attr.bsTooltip && scope.$watch(attr.bsTooltip, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.title = newValue;\n }\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n newValue === true ? tooltip.show() : tooltip.hide();\n });\n\n // Enabled binding support\n attr.bsEnabled && scope.$watch(attr.bsEnabled, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n newValue === false ? tooltip.setEnabled(false) : tooltip.setEnabled(true);\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n tooltip.setViewport(newValue);\n });\n\n // Initialize popover\n var tooltip = $tooltip(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(tooltip) tooltip.destroy();\n options = null;\n tooltip = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$typeahead', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'typeahead',\n prefixEvent: '$typeahead',\n placement: 'bottom-left',\n template: 'typeahead/typeahead.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n minLength: 1,\n filter: 'filter',\n limit: 6,\n autoSelect: false,\n comparator: '',\n trimValue: true\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n\n function TypeaheadFactory(element, controller, config) {\n\n var $typeahead = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $typeahead = $tooltip(element, options);\n var parentScope = config.scope;\n var scope = $typeahead.$scope;\n\n scope.$resetMatches = function(){\n scope.$matches = [];\n scope.$activeIndex = options.autoSelect ? 0 : -1; // If set to 0, the first match will be highlighted\n };\n scope.$resetMatches();\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $typeahead.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $typeahead.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $typeahead.$isVisible();\n };\n\n // Public methods\n\n $typeahead.update = function(matches) {\n scope.$matches = matches;\n if(scope.$activeIndex >= matches.length) {\n scope.$activeIndex = options.autoSelect ? 0: -1;\n }\n\n // When the placement is not one of the bottom placements, re-calc the positioning\n // so the results render correctly.\n if (/^(bottom|bottom-left|bottom-right)$/.test(options.placement)) return;\n\n // wrap in a $timeout so the results are updated\n // before repositioning\n $timeout($typeahead.$applyPlacement);\n };\n\n $typeahead.activate = function(index) {\n scope.$activeIndex = index;\n };\n\n $typeahead.select = function(index) {\n if(index === -1) return;\n var value = scope.$matches[index].value;\n // console.log('$setViewValue', value);\n controller.$setViewValue(value);\n controller.$render();\n scope.$resetMatches();\n if(parentScope) parentScope.$digest();\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $typeahead);\n };\n\n // Protected methods\n\n $typeahead.$isVisible = function() {\n if(!options.minLength || !controller) {\n return !!scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength;\n };\n\n $typeahead.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $typeahead.$onMouseDown = function(evt) {\n // Prevent blur on mousedown\n evt.preventDefault();\n evt.stopPropagation();\n };\n\n $typeahead.$onKeyDown = function(evt) {\n if(!/(38|40|13)/.test(evt.keyCode)) return;\n\n // Let ngSubmit pass if the typeahead tip is hidden or no option is selected\n if($typeahead.$isVisible() && !(evt.keyCode === 13 && scope.$activeIndex === -1)) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n // Select with enter\n if(evt.keyCode === 13 && scope.$matches.length) {\n $typeahead.select(scope.$activeIndex);\n }\n\n // Navigate with keyboard\n else if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n };\n\n // Overrides\n\n var show = $typeahead.show;\n $typeahead.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $typeahead.$onKeyDown);\n }\n }, 0, false);\n };\n\n var hide = $typeahead.hide;\n $typeahead.hide = function() {\n $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $typeahead.$onKeyDown);\n }\n if(!options.autoSelect)\n $typeahead.activate(-1);\n hide();\n };\n\n return $typeahead;\n\n }\n\n TypeaheadFactory.defaults = defaults;\n return TypeaheadFactory;\n\n };\n\n })\n\n .directive('bsTypeahead', function($window, $parse, $q, $typeahead, $parseOptions) {\n\n var defaults = $typeahead.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'filter', 'limit', 'minLength', 'watchOptions', 'selectMode', 'autoSelect', 'comparator', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'trimValue'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n });\n\n // Disable browser autocompletion\n element.attr('autocomplete' ,'off');\n\n // Build proper bsOptions\n var filter = options.filter || defaults.filter;\n var limit = options.limit || defaults.limit;\n var comparator = options.comparator || defaults.comparator;\n\n var bsOptions = attr.bsOptions;\n if(filter) bsOptions += ' | ' + filter + ':$viewValue';\n if (comparator) bsOptions += ':' + comparator;\n if(limit) bsOptions += ' | limitTo:' + limit;\n var parsedOptions = $parseOptions(bsOptions);\n\n // Initialize typeahead\n var typeahead = $typeahead(element, controller, options);\n\n // Watch options on demand\n if(options.watchOptions) {\n // Watch bsOptions values before filtering for changes, drop function calls\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n scope.$watchCollection(watchedOptions, function (newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller).then(function (values) {\n typeahead.update(values);\n controller.$render();\n });\n });\n }\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('$watch', element.attr('ng-model'), newValue);\n scope.$modelValue = newValue; // Publish modelValue on scope for custom templates\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n // Prevent input with no future prospect if selectMode is truthy\n // @TODO test selectMode\n if(options.selectMode && !values.length && newValue.length > 0) {\n controller.$setViewValue(controller.$viewValue.substring(0, controller.$viewValue.length - 1));\n return;\n }\n if(values.length > limit) values = values.slice(0, limit);\n var isVisible = typeahead.$isVisible();\n isVisible && typeahead.update(values);\n // Do not re-queue an update if a correct value has been selected\n if(values.length === 1 && values[0].value === newValue) return;\n !isVisible && typeahead.update(values);\n // Queue a new rendering that will leverage collection loading\n controller.$render();\n });\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var displayValue = parsedOptions.displayValue(modelValue);\n return displayValue === undefined ? '' : displayValue;\n });\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n if(controller.$isEmpty(controller.$viewValue)) return element.val('');\n var index = typeahead.$getIndex(controller.$modelValue);\n var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;\n selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;\n var value = selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '') : '';\n element.val(options.trimValue === false ? value : value.trim());\n };\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (typeahead) typeahead.destroy();\n options = null;\n typeahead = null;\n });\n\n }\n };\n\n });\n"],"sourceRoot":"/source/"}
1
+ {"version":3,"sources":["angular-strap.js","affix/affix.js","alert/alert.js","aside/aside.js","collapse/collapse.js","datepicker/datepicker.js","dropdown/dropdown.js","button/button.js","helpers/date-formatter.js","helpers/date-parser.js","helpers/debounce.js","helpers/dimensions.js","helpers/parse-options.js","helpers/raf.js","modal/modal.js","navbar/navbar.js","popover/popover.js","scrollspy/scrollspy.js","select/select.js","tab/tab.js","timepicker/timepicker.js","tooltip/tooltip.js","typeahead/typeahead.js"],"names":["window","document","undefined","angular","bodyEl","$window","body","windowEl","defaults","AffixFactory","offsetTop","$affix","inlineStyles","options","this","$get","reset","setWidth","initialAffixTop","offsetParent","match","getRequiredAffixClass","unpin","position","top","scrollTop","getScrollTop","scrollHeight","getScrollHeight","targetEl","pageYOffset","directive","parent","target","initialOffsetTop","offsetBottom","affixed","element","init","i","$parseOffsets","on","checkPosition","require","checkPositionWithEventLoop","dimensions","offset","destroy","style","width","off","affix","setTimeout","elementHeight","height","css","addClass","offsetUnpin","offsetHeight","offsetWidth","$debouncedOnResize","$onResize","initialPosition","restrict","affixTarget","$element","forEach","link","key","scope","option","$on","attr","test","controller","animation","prefixClass","container","provider","backdrop","keyboard","show","duration","type","dismissable","AlertFactory","$alert","$scope","config","extend","$timeout","hide","isDefined","falseValueRegExp","hasOwnProperty","title","newValue","oldValue","trustAsHtml","bsAlert","$observe","content","alert","trigger","toggle","module","contentTemplate","html","AsideFactory","$aside","requestAnimationFrame","$modal","bsAside","$watch","aside","self","startCollapsed","allowMultiple","$attrs","activeIndexes","$targets","$active","length","index","value","indexOf","activeItems","splice","activateItem","$options","$collapse","copy","$toggles","push","$unregisterToggle","$registerToggle","$unregisterTarget","deactivateItem","$viewChangeListeners","fn","fixActiveItemIndexes","$setActive","disallowToggle","isActive","$activeIndexes","bsCollapseCtrl","controllers","$animate","ngModelCtrl","$setViewValue","$formatters","attrs","modelValue","isArray","bsCollapseToggle","$apply","$registerTarget","render","active","action","activeClass","delay","useNative","dateType","dateFormat","timezone","modelDateFormat","dayFormat","monthFormat","yearFormat","monthTitleFormat","yearTitleFormat","strictFormat","autoclose","minDate","Infinity","maxDate","startView","minView","startWeek","daysOfWeekDisabled","iconLeft","iconRight","isNative","DatepickerFactory","parentScope","$datepicker","pickerViews","views","el","selected","date","focus","viewDate","$iconLeft","$iconRight","$picker","$views","$mode","datepickerViews","$selectPane","$toggleMode","setMode","select","isDate","$build","updateDisabledDates","disabledDateRanges","dateRanges","$date","$dateValue","$render","keep","Date","year","getFullYear","month","getDate","mode","pristine","call","$updateSelected","rows","built","$isSelected","$setDisabledEl","disabled","isDisabled","steps","targetDate","getUTCFullYear","getUTCMonth","UTC","$onMouseDown","evt","preventDefault","stopPropagation","isTouch","getUTCDate","$onKeyDown","nodeName","keyCode","shiftKey","altKey","updateSelected","onKeyDown","$digest","prop","focusElement","_init","_destroy","_show","_hide","blur","previousValue","normalizeDateRanges","ranges","disabledRanges","datepicker","isMaxValid","isValid","isMinValid","isNaN","parsedDate","getTime","$parsers","unshift","viewValue","$setValidity","getDateFormattedString","formatDate","bsShow","lang","format","$dateFormatter","dateParser","$dateParser","strict","validateAgainstMinMaxDate","ngModel","getDateForAttribute","disabledDates","parse","timezoneOffsetAdjust","isUndefined","NaN","daySplit","arr","mod","n","m","arrays","size","$sce","weekDaysMin","weekdaysShort","weekDaysLabelsHtml","startDate","picker","weekDaysLabels","slice","concat","split","getMonth","update","firstDayOfMonth","firstDate","getDay","today","firstDateOffset","build","day","days","isToday","toDateString","label","muted","showLabels","labels","time","isSelected","newDate","name","firstMonth","months","lastDate","actualMonth","parseInt","firstYear","years","actualYear","setYear","placement","matchesSelector","DropdownFactory","$dropdown","onBodyClick","items","querySelectorAll","$rootScope","$new","parentEl","hasClass","$isShown","removeClass","prototype","transclusion","bsDropdown","dropdown","isString","compile","children","childEl","removeAttr","child","$button","constantValueRegExp","isInput","trueValue","falseValue","hasExoticValues","equals","checked","activeElement","bind","toggleEvent","$modelValue","$$rAF","toggleClass","getDefaultLocale","splitTimeFormat","timeFormat","exec","DATETIME_FORMATS","$locale","id","getDatetimeFormat","SHORTDAY","hoursFormat","minutesFormat","secondsFormat","timeSeparator","showSeconds","dateFilter","ParseDate","seconds","$localeProvider","milliseconds","hours","array","isNumeric","parseFloat","isFinite","indexOfCaseInsensitive","len","str","toString","toLowerCase","DateParserFactory","minutes","getHours","getMilliseconds","getMinutes","proto","noop","toDate","regExpMap","sss","mm","keys","setFnMap","map","clonedFormat","search","v","sortedMap","regExpForFormat","re","join","text","replace","Object","escapeReservedSymbols","RegExp","regex","HH","H","hh","h","a","EEEE","EEE","dd","d","MMMM","MMM","SHORTMONTH","MM","M","DAY","yyyy","yy","y","MONTH","ss","setSeconds","s","setMinutes","setHours","setDate","setMonth","setFullYear","$format","baseDate","setMap","formatRegex","formatSetMap","setMapForFormat","matches","fromDate","substr","getTimeForAttribute","daylightSavingAdjust","undo","func","timeout","context","factory","immediate","apply","args","cancel","callNow","leading","trailing","wait","currentStyle","getComputedStyle","extra","boxRect","getBoundingClientRect","left","docElement","ownerDocument","curPosition","curLeft","curCSSTop","documentElement","clientTop","pageXOffset","scrollLeft","clientLeft","curCSSLeft","calculatePosition","curTop","curOffset","curElem","props","isFunction","using","offsetParentRect","offsetParentElement","outer","$parseOptions","$values","regexp","$match","displayFn","locals","valueName","valueFn","ParseOptionsFactory","groupByFn","valuesFn","$parse","keyName","cancelAnimationFrame","when","values","parseValues","raf","webkitRequestAnimationFrame","mozRequestAnimationFrame","rafSupported","timer","prefixEvent","template","trim","bodyElement","htmlReplaceRegExp","ModalFactory","enterAnimateCallback","version","minor","modalElement","currentTarget","safeDigest","preventEventDefault","$hide","$$postDigest","$id","$show","$promise","templateEl","fetchTemplate","outerHTML","then","modalLinker","backdropElement","right","z-index","data","$compile","remove","$destroy","after","isElement","$emit","defaultPrevented","clonedElement","display","enter","backdropAnimation","hideOnBackdropClick","$onKeyUp","leave","leaveAnimateCallback","which","fetchPromises","cache","$templateCache","res","$http","get","bsModal","modal","routeAttr","$navbar","liElements","li","liElement","pattern","path","autoClose","$popover","PopoverFactory","$tooltip","dataTarget","popover","bsPopover","isObject","$applyPlacement","setViewport","viewport","spies","$document","debounce","throttle","ScrollSpyFactory","scrollEl","isWindowSpy","scrollId","$$count","$scrollspy","unbindViewContentLoaded","unbindIncludeContentLoaded","trackedElements","$trackedElements","sortedElements","activeTarget","debouncedCheckPosition","viewportHeight","throttledCheckPosition","debouncedCheckOffsets","checkOffsets","docEl","$activateElement","source","$getTrackedElement","filter","targetElement","querySelector","trackedElement","b","trackElement","toDelete","untrackElement","activate","scrollspy","multiple","allNoneButtons","sort","caretHtml","placeholder","allText","noneText","maxLength","maxLengthHtml","iconCheckmark","SelectFactory","$select","$activeIndex","$isMultiple","$showAllNoneButtons","$allText","$iconCheckmark","$isActive","$isVisible","$selectNone","$matches","$updateActiveIndex","$getIndex","minLength","$viewValue","l","dataMultiple","inputEl","watchedOptions","$watchCollection","parsedOptions","bsOptions","$isEmpty","navClass","$activeClass","$panes","$activePaneChangeListeners","$push","pane","$navClass","$remove","activeIndex","$pane","$tab","transclude","templateUrl","postLink","bsTabsCtrl","bsActivePane","parsedBsActivePane","assign","timeType","modelTimeFormat","minTime","maxTime","hourStep","minuteStep","secondStep","roundDisplay","iconUp","iconDown","arrowBehavior","timepickerFactory","hour","meridian","coeff","selRange","end","start","setSelectionRange","collapse","selectionStart","moveStart","selectionEnd","moveEnd","$timepicker","floorMinutes","floor","selectedIndex","defaultDate","second","getSeconds","millisecond","$iconUp","$iconDown","$moveIndex","$switchMeridian","switchMeridian","minute","midIndex","$isDisabled","showAM","isAM","selectedTime","$arrowAction","$setTimeByStep","hoursLength","triggerHandler","secondsLength","sepLength","lateralMove","count","minutesLength","selectRange","incr","isSeconds","isMeridian","createSelection","createTextRange","parsedTime","getTimeFormattedString","timepicker","validateAgainstMinMaxTime","bsEnabled","selector","padding","String","$body","_tipToHide","tipElement","triggers","unbindTriggerEvents","bindKeyboardEvents","$onFocusElementMouseDown","unbindKeyboardEvents","_autoCloseEventsBinded","bindAutoCloseEvents","unbindAutoCloseEvents","stopEventPropagation","event","getPosition","rect","elRect","p","scroll","isBody","getCalculatedOffset","actualWidth","actualHeight","outerDims","clientWidth","innerHeight","tip","marginTop","marginLeft","setOffset","delta","getViewportAdjustedDelta","isVertical","replaceArrow","arrowDelta","arrowOffsetPosition","viewportPadding","topEdgeOffset","$viewport","viewportDimensions","leftEdgeOffset","rightEdgeOffset","dimension","isHorizontal","findElement","$arrow","clearTimeout","tipScope","$$phase","$setEnabled","setEnabled","isEnabled","contentEl","tipLinker","tipTemplate","isNumber","tipContainer","bindTriggerEvents","destroyTipElement","hoverState","lastChild","visibility","customClass","_blur","elementPosition","autoPlace","originalPlacement","containerPosition","tipHeight","tipPosition","applyPlacement","tipWidth","TooltipFactory","$location","tooltip","bsTooltip","limit","autoSelect","comparator","trimValue","$typeahead","$resetMatches","TypeaheadFactory","typeahead","watchOptions","selectMode","isVisible","displayValue","val"],"mappings":"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","file":"angular-strap.min.js","sourcesContent":["(function(window, document, undefined) {\n'use strict';\n\n// Source: module.js\nangular.module('mgcrea.ngStrap', [\n 'mgcrea.ngStrap.modal',\n 'mgcrea.ngStrap.aside',\n 'mgcrea.ngStrap.alert',\n 'mgcrea.ngStrap.button',\n 'mgcrea.ngStrap.select',\n 'mgcrea.ngStrap.datepicker',\n 'mgcrea.ngStrap.timepicker',\n 'mgcrea.ngStrap.navbar',\n 'mgcrea.ngStrap.tooltip',\n 'mgcrea.ngStrap.popover',\n 'mgcrea.ngStrap.dropdown',\n 'mgcrea.ngStrap.typeahead',\n 'mgcrea.ngStrap.scrollspy',\n 'mgcrea.ngStrap.affix',\n 'mgcrea.ngStrap.tab',\n 'mgcrea.ngStrap.collapse'\n]);\n\n// Source: affix/affix.js\nangular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mgcrea.ngStrap.helpers.debounce'])\n\n .provider('$affix', function() {\n\n var defaults = this.defaults = {\n offsetTop: 'auto',\n inlineStyles: true\n };\n\n this.$get = function($window, debounce, dimensions) {\n\n var bodyEl = angular.element($window.document.body);\n var windowEl = angular.element($window);\n\n function AffixFactory(element, config) {\n\n var $affix = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var targetEl = options.target;\n\n // Initial private vars\n var reset = 'affix affix-top affix-bottom',\n setWidth = false,\n initialAffixTop = 0,\n initialOffsetTop = 0,\n offsetTop = 0,\n offsetBottom = 0,\n affixed = null,\n unpin = null;\n\n var parent = element.parent();\n // Options: custom parent\n if (options.offsetParent) {\n if (options.offsetParent.match(/^\\d+$/)) {\n for (var i = 0; i < (options.offsetParent * 1) - 1; i++) {\n parent = parent.parent();\n }\n }\n else {\n parent = angular.element(options.offsetParent);\n }\n }\n\n $affix.init = function() {\n\n this.$parseOffsets();\n initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n setWidth = !element[0].style.width;\n\n // Bind events\n targetEl.on('scroll', this.checkPosition);\n targetEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', this.$debouncedOnResize);\n\n // Both of these checkPosition() calls are necessary for the case where\n // the user hits refresh after scrolling to the bottom of the page.\n this.checkPosition();\n this.checkPositionWithEventLoop();\n\n };\n\n $affix.destroy = function() {\n\n // Unbind events\n targetEl.off('scroll', this.checkPosition);\n targetEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', this.$debouncedOnResize);\n\n };\n\n $affix.checkPositionWithEventLoop = function() {\n\n // IE 9 throws an error if we use 'this' instead of '$affix'\n // in this setTimeout call\n setTimeout($affix.checkPosition, 1);\n\n };\n\n $affix.checkPosition = function() {\n // if (!this.$element.is(':visible')) return\n\n var scrollTop = getScrollTop();\n var position = dimensions.offset(element[0]);\n var elementHeight = dimensions.height(element[0]);\n\n // Get required affix class according to position\n var affix = getRequiredAffixClass(unpin, position, elementHeight);\n\n // Did affix status changed this last check?\n if(affixed === affix) return;\n affixed = affix;\n\n // Add proper affix class\n element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\n\n if(affix === 'top') {\n unpin = null;\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', '');\n }\n } else if(affix === 'bottom') {\n if (options.offsetUnpin) {\n unpin = -(options.offsetUnpin * 1);\n }\n else {\n // Calculate unpin threshold when affixed to bottom.\n // Hopefully the browser scrolls pixel by pixel.\n unpin = position.top - scrollTop;\n }\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n }\n } else { // affix === 'middle'\n unpin = null;\n if(setWidth) {\n element.css('width', element[0].offsetWidth + 'px');\n }\n if (options.inlineStyles) {\n element.css('position', 'fixed');\n element.css('top', initialAffixTop + 'px');\n }\n }\n\n };\n\n $affix.$onResize = function() {\n $affix.$parseOffsets();\n $affix.checkPosition();\n };\n $affix.$debouncedOnResize = debounce($affix.$onResize, 50);\n\n $affix.$parseOffsets = function() {\n var initialPosition = element.css('position');\n // Reset position to calculate correct offsetTop\n if (options.inlineStyles){\n element.css('position', (options.offsetParent) ? '' : 'relative');\n }\n\n if(options.offsetTop) {\n if(options.offsetTop === 'auto') {\n options.offsetTop = '+0';\n }\n if(options.offsetTop.match(/^[-+]\\d+$/)) {\n initialAffixTop = - options.offsetTop * 1;\n if(options.offsetParent) {\n offsetTop = dimensions.offset(parent[0]).top + (options.offsetTop * 1);\n }\n else {\n offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\n }\n }\n else {\n offsetTop = options.offsetTop * 1;\n }\n }\n\n if(options.offsetBottom) {\n if(options.offsetParent && options.offsetBottom.match(/^[-+]\\d+$/)) {\n // add 1 pixel due to rounding problems...\n offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + (options.offsetBottom * 1) + 1;\n }\n else {\n offsetBottom = options.offsetBottom * 1;\n }\n }\n\n // Bring back the element's position after calculations\n if (options.inlineStyles){\n element.css('position', initialPosition);\n }\n };\n\n // Private methods\n\n function getRequiredAffixClass(unpin, position, elementHeight) {\n\n var scrollTop = getScrollTop();\n var scrollHeight = getScrollHeight();\n\n if(scrollTop <= offsetTop) {\n return 'top';\n } else if(unpin !== null && (scrollTop + unpin <= position.top)) {\n return 'middle';\n } else if(offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n return 'bottom';\n } else {\n return 'middle';\n }\n\n }\n\n function getScrollTop() {\n return targetEl[0] === $window ? $window.pageYOffset : targetEl[0].scrollTop;\n }\n\n function getScrollHeight() {\n return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight;\n }\n\n $affix.init();\n return $affix;\n\n }\n\n return AffixFactory;\n\n };\n\n })\n\n .directive('bsAffix', function($affix, $window) {\n\n return {\n restrict: 'EAC',\n require: '^?bsAffixTarget',\n link: function postLink(scope, element, attr, affixTarget) {\n\n var options = {scope: scope, target: affixTarget ? affixTarget.$element : angular.element($window)};\n angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin', 'inlineStyles'], function(key) {\n if(angular.isDefined(attr[key])) {\n var option = attr[key];\n if (/true/i.test(option)) option = true;\n if (/false/i.test(option)) option = false;\n options[key] = option;\n }\n });\n\n var affix = $affix(element, options);\n scope.$on('$destroy', function() {\n affix && affix.destroy();\n options = null;\n affix = null;\n });\n\n }\n };\n\n })\n\n .directive('bsAffixTarget', function() {\n return {\n controller: function($element) {\n this.$element = $element;\n }\n };\n });\n\n// Source: alert/alert.js\n// @BUG: following snippet won't compile correctly\n// @TODO: submit issue to core\n// '<span ng-if=\"title\"><strong ng-bind=\"title\"></strong>&nbsp;</span><span ng-bind-html=\"content\"></span>' +\n\nangular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal'])\n\n .provider('$alert', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'alert',\n prefixEvent: 'alert',\n placement: null,\n template: 'alert/alert.tpl.html',\n container: false,\n element: null,\n backdrop: false,\n keyboard: true,\n show: true,\n // Specific options\n duration: false,\n type: false,\n dismissable: true\n };\n\n this.$get = function($modal, $timeout) {\n\n function AlertFactory(config) {\n\n var $alert = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $alert = $modal(options);\n\n // Support scope as string options [/*title, content, */ type, dismissable]\n $alert.$scope.dismissable = !!options.dismissable;\n if(options.type) {\n $alert.$scope.type = options.type;\n }\n\n // Support auto-close duration\n var show = $alert.show;\n if(options.duration) {\n $alert.show = function() {\n show();\n $timeout(function() {\n $alert.hide();\n }, options.duration * 1000);\n };\n }\n\n return $alert;\n\n }\n\n return AlertFactory;\n\n };\n\n })\n\n .directive('bsAlert', function($window, $sce, $alert) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'placement', 'keyboard', 'html', 'container', 'animation', 'duration', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['keyboard', 'html', 'container', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content', 'type'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAlert && scope.$watch(attr.bsAlert, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize alert\n var alert = $alert(options);\n\n // Trigger\n element.on(attr.trigger || 'click', alert.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (alert) alert.destroy();\n options = null;\n alert = null;\n });\n\n }\n };\n\n });\n\n// Source: aside/aside.js\nangular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal'])\n\n .provider('$aside', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade-and-slide-right',\n prefixClass: 'aside',\n prefixEvent: 'aside',\n placement: 'right',\n template: 'aside/aside.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($modal) {\n\n function AsideFactory(config) {\n\n var $aside = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $aside = $modal(options);\n\n return $aside;\n\n }\n\n return AsideFactory;\n\n };\n\n })\n\n .directive('bsAside', function($window, $sce, $aside) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAside && scope.$watch(attr.bsAside, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize aside\n var aside = $aside(options);\n\n // Trigger\n element.on(attr.trigger || 'click', aside.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (aside) aside.destroy();\n options = null;\n aside = null;\n });\n\n }\n };\n\n });\n\n// Source: collapse/collapse.js\nangular.module('mgcrea.ngStrap.collapse', [])\n\n .provider('$collapse', function() {\n\n var defaults = this.defaults = {\n animation: 'am-collapse',\n disallowToggle: false,\n activeClass: 'in',\n startCollapsed: false,\n allowMultiple: false\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['disallowToggle', 'startCollapsed', 'allowMultiple'], function(key) {\n if(angular.isDefined($attrs[key]) && falseValueRegExp.test($attrs[key]))\n self.$options[key] = false;\n });\n\n self.$toggles = [];\n self.$targets = [];\n\n self.$viewChangeListeners = [];\n\n self.$registerToggle = function(element) {\n self.$toggles.push(element);\n };\n self.$registerTarget = function(element) {\n self.$targets.push(element);\n };\n\n self.$unregisterToggle = function(element) {\n var index = self.$toggles.indexOf(element);\n // remove toggle from $toggles array\n self.$toggles.splice(index, 1);\n };\n self.$unregisterTarget = function(element) {\n var index = self.$targets.indexOf(element);\n\n // remove element from $targets array\n self.$targets.splice(index, 1);\n\n if (self.$options.allowMultiple) {\n // remove target index from $active array values\n deactivateItem(element);\n }\n\n // fix active item indexes\n fixActiveItemIndexes(index);\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n // use array to store all the currently open panels\n self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n self.$setActive = $scope.$setActive = function(value) {\n if(angular.isArray(value)) {\n self.$targets.$active = value;\n }\n else if(!self.$options.disallowToggle) {\n // toogle element active status\n isActive(value) ? deactivateItem(value) : activateItem(value);\n } else {\n activateItem(value);\n }\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$activeIndexes = function() {\n return self.$options.allowMultiple ? self.$targets.$active :\n self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n };\n\n function fixActiveItemIndexes(index) {\n // item with index was removed, so we\n // need to adjust other items index values\n var activeIndexes = self.$targets.$active;\n for(var i = 0; i < activeIndexes.length; i++) {\n if (index < activeIndexes[i]) {\n activeIndexes[i] = activeIndexes[i] - 1;\n }\n\n // the last item is active, so we need to\n // adjust its index\n if (activeIndexes[i] === self.$targets.length) {\n activeIndexes[i] = self.$targets.length - 1;\n }\n }\n }\n\n function isActive(value) {\n var activeItems = self.$targets.$active;\n return activeItems.indexOf(value) === -1 ? false : true;\n }\n\n function deactivateItem(value) {\n var index = self.$targets.$active.indexOf(value);\n if (index !== -1) {\n self.$targets.$active.splice(index, 1);\n }\n }\n\n function activateItem(value) {\n if (!self.$options.allowMultiple) {\n // remove current selected item\n self.$targets.$active.splice(0, 1);\n }\n\n if (self.$targets.$active.indexOf(value) === -1) {\n self.$targets.$active.push(value);\n }\n }\n\n };\n\n this.$get = function() {\n var $collapse = {};\n $collapse.defaults = defaults;\n $collapse.controller = controller;\n return $collapse;\n };\n\n })\n\n .directive('bsCollapse', function($window, $animate, $collapse) {\n\n var defaults = $collapse.defaults;\n\n return {\n require: ['?ngModel', 'bsCollapse'],\n controller: ['$scope', '$element', '$attrs', $collapse.controller],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n if (angular.isArray(modelValue)) {\n // model value is an array, so just replace\n // the active items directly\n bsCollapseCtrl.$setActive(modelValue);\n }\n else {\n var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n if (angular.isArray(activeIndexes)) {\n // we have an array of selected indexes\n if (activeIndexes.indexOf(modelValue * 1) === -1) {\n // item with modelValue index is not active\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n else if (activeIndexes !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n return modelValue;\n });\n\n }\n\n }\n };\n\n })\n\n .directive('bsCollapseToggle', function() {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base attr\n element.attr('data-toggle', 'collapse');\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerToggle(element);\n\n // remove toggle from collapse controller when toggle is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterToggle(element);\n });\n\n element.on('click', function() {\n var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n bsCollapseCtrl.$setActive(index * 1);\n scope.$apply();\n });\n\n }\n };\n\n })\n\n .directive('bsCollapseTarget', function($animate) {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n // scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base class\n element.addClass('collapse');\n\n // Add animation class\n if(bsCollapseCtrl.$options.animation) {\n element.addClass(bsCollapseCtrl.$options.animation);\n }\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerTarget(element);\n\n // remove pane target from collapse controller when target is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterTarget(element);\n });\n\n function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$activeIndexes();\n var action = 'removeClass';\n if (angular.isArray(active)) {\n if (active.indexOf(index) !== -1) {\n action = 'addClass';\n }\n }\n else if (index === active) {\n action = 'addClass';\n }\n\n $animate[action](element, bsCollapseCtrl.$options.activeClass);\n }\n\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n\n// Source: datepicker/datepicker.js\nangular.module('mgcrea.ngStrap.datepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$datepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'datepicker',\n prefixClass: 'datepicker',\n placement: 'bottom-left',\n template: 'datepicker/datepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: false,\n dateType: 'date',\n dateFormat: 'shortDate',\n timezone: null,\n modelDateFormat: null,\n dayFormat: 'dd',\n monthFormat: 'MMM',\n yearFormat: 'yyyy',\n monthTitleFormat: 'MMMM yyyy',\n yearTitleFormat: 'yyyy',\n strictFormat: false,\n autoclose: false,\n minDate: -Infinity,\n maxDate: +Infinity,\n startView: 0,\n minView: 0,\n startWeek: 0,\n daysOfWeekDisabled: '',\n iconLeft: 'glyphicon glyphicon-chevron-left',\n iconRight: 'glyphicon glyphicon-chevron-right'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function DatepickerFactory(element, controller, config) {\n\n var $datepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $datepicker.$options;\n var scope = $datepicker.$scope;\n if(options.startView) options.startView -= options.minView;\n\n // View vars\n\n var pickerViews = datepickerViews($datepicker);\n $datepicker.$views = pickerViews.views;\n var viewDate = pickerViews.viewDate;\n scope.$mode = options.startView;\n scope.$iconLeft = options.iconLeft;\n scope.$iconRight = options.iconRight;\n var $picker = $datepicker.$views[scope.$mode];\n\n // Scope methods\n\n scope.$select = function(date) {\n $datepicker.select(date);\n };\n scope.$selectPane = function(value) {\n $datepicker.$selectPane(value);\n };\n scope.$toggleMode = function() {\n $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);\n };\n\n // Public methods\n\n $datepicker.update = function(date) {\n // console.warn('$datepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $datepicker.$date = date;\n $picker.update.call($picker, date);\n }\n // Build only if pristine\n $datepicker.$build(true);\n };\n\n $datepicker.updateDisabledDates = function(dateRanges) {\n options.disabledDateRanges = dateRanges;\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);\n }\n };\n\n $datepicker.select = function(date, keep) {\n // console.warn('$datepicker.select', date, scope.$mode);\n if(!angular.isDate(controller.$dateValue)) controller.$dateValue = new Date(date);\n if(!scope.$mode || keep) {\n controller.$setViewValue(angular.copy(date));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $datepicker.hide(true); });\n }\n } else {\n angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});\n $datepicker.setMode(scope.$mode - 1);\n $datepicker.$build();\n }\n };\n\n $datepicker.setMode = function(mode) {\n // console.warn('$datepicker.setMode', mode);\n scope.$mode = mode;\n $picker = $datepicker.$views[scope.$mode];\n $datepicker.$build();\n };\n\n // Protected methods\n\n $datepicker.$build = function(pristine) {\n // console.warn('$datepicker.$build() viewDate=%o', viewDate);\n if(pristine === true && $picker.built) return;\n if(pristine === false && !$picker.built) return;\n $picker.build.call($picker);\n };\n\n $datepicker.$updateSelected = function() {\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], updateSelected);\n }\n };\n\n $datepicker.$isSelected = function(date) {\n return $picker.isSelected(date);\n };\n\n $datepicker.$setDisabledEl = function(el) {\n el.disabled = $picker.isDisabled(el.date);\n };\n\n $datepicker.$selectPane = function(value) {\n var steps = $picker.steps;\n // set targetDate to first day of month to avoid problems with\n // date values rollover. This assumes the viewDate does not\n // depend on the day of the month\n var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));\n angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});\n $datepicker.$build();\n };\n\n $datepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $datepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n if(evt.keyCode === 13) {\n if(!scope.$mode) {\n return $datepicker.hide(true);\n } else {\n return scope.$apply(function() { $datepicker.setMode(scope.$mode - 1); });\n }\n }\n\n // Navigate with keyboard\n $picker.onKeyDown(evt);\n parentScope.$digest();\n };\n\n // Private\n\n function updateSelected(el) {\n el.selected = $datepicker.$isSelected(el.date);\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $datepicker.init;\n $datepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'date');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $datepicker.destroy;\n $datepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $datepicker.show;\n $datepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // if $datepicker is no longer showing, don't setup events\n if(!$datepicker.$isShown) return;\n $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $datepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $datepicker.hide;\n $datepicker.hide = function(blur) {\n if(!$datepicker.$isShown) return;\n $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $datepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $datepicker;\n\n }\n\n DatepickerFactory.defaults = defaults;\n return DatepickerFactory;\n\n };\n\n })\n\n .directive('bsDatepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {\n\n var defaults = $datepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'timezone', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!datepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);\n newValue === true ? datepicker.show() : datepicker.hide();\n });\n\n // Initialize datepicker\n var datepicker = $datepicker(element, controller, options);\n options = datepicker.$options;\n // Set expected iOS format\n if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';\n\n var lang = options.lang;\n\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n // Observe attributes for changes\n angular.forEach(['minDate', 'maxDate'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n // console.warn('attr.$observe(%s)=%o', key, newValue);\n datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);\n // Build only if dirty\n !isNaN(datepicker.$options[key]) && datepicker.$build(false);\n validateAgainstMinMaxDate(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n datepicker.update(controller.$dateValue);\n }, true);\n\n // Normalize undefined/null/empty array,\n // so that we don't treat changing from undefined->null as a change.\n function normalizeDateRanges(ranges) {\n if (!ranges || !ranges.length) return null;\n return ranges;\n }\n\n if (angular.isDefined(attr.disabledDates)) {\n scope.$watch(attr.disabledDates, function(disabledRanges, previousValue) {\n disabledRanges = normalizeDateRanges(disabledRanges);\n previousValue = normalizeDateRanges(previousValue);\n\n if (disabledRanges) {\n datepicker.updateDisabledDates(disabledRanges);\n }\n });\n }\n\n function validateAgainstMinMaxDate(parsedDate) {\n if (!angular.isDate(parsedDate)) return;\n var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;\n var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(isValid) controller.$dateValue = parsedDate;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n controller.$setValidity('date', true);\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n return null;\n }\n var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedDate || isNaN(parsedDate.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxDate(parsedDate);\n }\n\n if(options.dateType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedDate, options.timezone, true);\n return formatDate(date, options.modelDateFormat || options.dateFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.dateType === 'number') {\n return date.getTime();\n } else if(options.dateType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.dateType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.dateType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelDateFormat);\n } else if(options.dateType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) {\n // var today = new Date();\n // date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n // }\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getDateFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getDateFormattedString());\n };\n\n function getDateFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(datepicker) datepicker.destroy();\n options = null;\n datepicker = null;\n });\n\n }\n };\n\n })\n\n .provider('datepickerViews', function() {\n\n var defaults = this.defaults = {\n dayFormat: 'dd',\n daySplit: 7\n };\n\n // Split array into smaller arrays\n function split(arr, size) {\n var arrays = [];\n while(arr.length > 0) {\n arrays.push(arr.splice(0, size));\n }\n return arrays;\n }\n\n // Modulus operator\n function mod(n, m) {\n return ((n % m) + m) % m;\n }\n\n this.$get = function($dateFormatter, $dateParser, $sce) {\n\n return function(picker) {\n\n var scope = picker.$scope;\n var options = picker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n var weekDaysLabelsHtml = $sce.trustAsHtml('<th class=\"dow text-center\">' + weekDaysLabels.join('</th><th class=\"dow text-center\">') + '</th>');\n\n var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n\n var views = [{\n format: options.dayFormat,\n split: 7,\n steps: { month: 1 },\n update: function(date, force) {\n if(!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getDate() !== viewDate.date || date.getDate() === 1) {\n // chaging picker current month will cause viewDate.date to be set to first day of the month,\n // in $datepicker.$selectPane, so picker would not update selected day display if\n // user picks first day of the new month.\n // As a workaround, we are always forcing update when picked date is first day of month.\n viewDate.date = picker.$date.getDate();\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5), firstDateOffset = firstDate.getTimezoneOffset();\n var today = dateParser.timezoneOffsetAdjust(new Date(), options.timezone).toDateString();\n // Handle daylight time switch\n if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);\n var days = [], day;\n for(var i = 0; i < 42; i++) { // < 7 * 6\n day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));\n days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n }\n scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);\n scope.showLabels = true;\n scope.labels = weekDaysLabelsHtml;\n scope.rows = split(days, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();\n },\n isDisabled: function(date) {\n var time = date.getTime();\n\n // Disabled because of min/max date.\n if (time < options.minDate || time > options.maxDate) return true;\n\n // Disabled due to being a disabled day of the week\n if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;\n\n // Disabled because of disabled date range.\n if (options.disabledDateRanges) {\n for (var i = 0; i < options.disabledDateRanges.length; i++) {\n if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {\n return true;\n }\n }\n }\n\n return false;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualTime = picker.$date.getTime();\n var newDate;\n\n if(evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);\n else if(evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);\n else if(evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);\n else if(evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'month',\n format: options.monthFormat,\n split: 4,\n steps: { year: 1 },\n update: function(date, force) {\n if(!this.built || date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstMonth = new Date(viewDate.year, 0, 1);\n var months = [], month;\n for (var i = 0; i < 12; i++) {\n month = new Date(viewDate.year, i, 1);\n months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n }\n scope.title = formatDate(month, options.yearTitleFormat);\n scope.showLabels = false;\n scope.rows = split(months, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualMonth = picker.$date.getMonth();\n var newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setMonth(actualMonth - 1);\n else if(evt.keyCode === 38) newDate.setMonth(actualMonth - 4);\n else if(evt.keyCode === 39) newDate.setMonth(actualMonth + 1);\n else if(evt.keyCode === 40) newDate.setMonth(actualMonth + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'year',\n format: options.yearFormat,\n split: 4,\n steps: { year: 12 },\n update: function(date, force) {\n if(!this.built || force || parseInt(date.getFullYear()/20, 10) !== parseInt(viewDate.year/20, 10)) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstYear = viewDate.year - viewDate.year % (this.split * 3);\n var years = [], year;\n for (var i = 0; i < 12; i++) {\n year = new Date(firstYear + i, 0, 1);\n years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});\n }\n scope.title = years[0].label + '-' + years[years.length - 1].label;\n scope.showLabels = false;\n scope.rows = split(years, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear() + 1, 0, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualYear = picker.$date.getFullYear(),\n newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setYear(actualYear - 1);\n else if(evt.keyCode === 38) newDate.setYear(actualYear - 4);\n else if(evt.keyCode === 39) newDate.setYear(actualYear + 1);\n else if(evt.keyCode === 40) newDate.setYear(actualYear + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }];\n\n return {\n views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,\n viewDate: viewDate\n };\n\n };\n\n };\n\n });\n\n// Source: dropdown/dropdown.js\nangular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$dropdown', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'dropdown',\n prefixEvent: 'dropdown',\n placement: 'bottom-left',\n template: 'dropdown/dropdown.tpl.html',\n trigger: 'click',\n container: false,\n keyboard: true,\n html: false,\n delay: 0\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;\n\n function DropdownFactory(element, config) {\n\n var $dropdown = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n $dropdown = $tooltip(element, options);\n var parentEl = element.parent();\n\n // Protected methods\n\n $dropdown.$onKeyDown = function(evt) {\n if (!/(38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Retrieve focused index\n var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));\n if(!items.length) return;\n var index;\n angular.forEach(items, function(el, i) {\n if(matchesSelector && matchesSelector.call(el, ':focus')) index = i;\n });\n\n // Navigate with keyboard\n if(evt.keyCode === 38 && index > 0) index--;\n else if(evt.keyCode === 40 && index < items.length - 1) index++;\n else if(angular.isUndefined(index)) index = 0;\n items.eq(index)[0].focus();\n\n };\n\n // Overrides\n\n var show = $dropdown.show;\n $dropdown.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n options.keyboard && $dropdown.$element && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n bodyEl.on('click', onBodyClick);\n }, 0, false);\n parentEl.hasClass('dropdown') && parentEl.addClass('open');\n };\n\n var hide = $dropdown.hide;\n $dropdown.hide = function() {\n if(!$dropdown.$isShown) return;\n options.keyboard && $dropdown.$element && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n bodyEl.off('click', onBodyClick);\n parentEl.hasClass('dropdown') && parentEl.removeClass('open');\n hide();\n };\n\n var destroy = $dropdown.destroy;\n $dropdown.destroy = function() {\n bodyEl.off('click', onBodyClick);\n destroy();\n };\n\n // Private functions\n\n function onBodyClick(evt) {\n if(evt.target === element[0]) return;\n return evt.target !== element[0] && $dropdown.hide();\n }\n\n return $dropdown;\n\n }\n\n return DropdownFactory;\n\n };\n\n })\n\n .directive('bsDropdown', function($window, $sce, $dropdown) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as an object\n attr.bsDropdown && scope.$watch(attr.bsDropdown, function(newValue, oldValue) {\n scope.content = newValue;\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!dropdown || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(dropdown),?/i);\n newValue === true ? dropdown.show() : dropdown.hide();\n });\n\n // Initialize dropdown\n var dropdown = $dropdown(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (dropdown) dropdown.destroy();\n options = null;\n dropdown = null;\n });\n\n }\n };\n\n });\n\n// Source: button/button.js\nangular.module('mgcrea.ngStrap.button', [])\n\n .provider('$button', function() {\n\n var defaults = this.defaults = {\n activeClass:'active',\n toggleEvent:'click'\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsCheckboxGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"checkbox\"]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.attr('bs-checkbox', '');\n childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));\n });\n }\n\n };\n\n })\n\n .directive('bsCheckbox', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support label > input[type=\"checkbox\"]\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;\n if(constantValueRegExp.test(attr.trueValue)) {\n trueValue = scope.$eval(attr.trueValue);\n }\n var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;\n if(constantValueRegExp.test(attr.falseValue)) {\n falseValue = scope.$eval(attr.falseValue);\n }\n\n // Parse exotic values\n var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';\n if(hasExoticValues) {\n controller.$parsers.push(function(viewValue) {\n // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue);\n return viewValue ? trueValue : falseValue;\n });\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n return angular.equals(modelValue, trueValue);\n });\n // Fix rendering for exotic values\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n controller.$render();\n });\n }\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, trueValue);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n if(!isInput) {\n controller.$setViewValue(!activeElement.hasClass('active'));\n }\n if(!hasExoticValues) {\n controller.$render();\n }\n });\n });\n\n }\n\n };\n\n })\n\n .directive('bsRadioGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"radio\"]');\n angular.forEach(children, function(child) {\n angular.element(child).attr('bs-radio', '');\n angular.element(child).attr('ng-model', attr.ngModel);\n });\n }\n\n };\n\n })\n\n .directive('bsRadio', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support `label > input[type=\"radio\"]` markup\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var value;\n attr.$observe('value', function(v) {\n value = constantValueRegExp.test(v) ? scope.$eval(v) : v;\n controller.$render();\n });\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, value);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n controller.$setViewValue(value);\n controller.$render();\n });\n });\n\n }\n\n };\n\n });\n\n// Source: helpers/date-formatter.js\nangular.module('mgcrea.ngStrap.helpers.dateFormatter', [])\n\n .service('$dateFormatter', function($locale, dateFilter) {\n\n // The unused `lang` arguments are on purpose. The default implementation does not\n // use them and it always uses the locale loaded into the `$locale` service.\n // Custom implementations might use it, thus allowing different directives to\n // have different languages.\n\n this.getDefaultLocale = function() {\n return $locale.id;\n };\n\n // Format is either a data format name, e.g. \"shortTime\" or \"fullDate\", or a date format\n // Return either the corresponding date format or the given date format.\n this.getDatetimeFormat = function(format, lang) {\n return $locale.DATETIME_FORMATS[format] || format;\n };\n\n this.weekdaysShort = function(lang) {\n return $locale.DATETIME_FORMATS.SHORTDAY;\n };\n\n function splitTimeFormat(format) {\n return /(h+)([:\\.])?(m+)([:\\.])?(s*)[ ]?(a?)/i.exec(format).slice(1);\n }\n\n // h:mm a => h\n this.hoursFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[0];\n };\n\n // h:mm a => mm\n this.minutesFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[2];\n };\n\n // h:mm:ss a => ss\n this.secondsFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => :\n this.timeSeparator = function(timeFormat) {\n return splitTimeFormat(timeFormat)[1];\n };\n\n // h:mm:ss a => true, h:mm a => false\n this.showSeconds = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => true, H.mm => false\n this.showAM = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[5];\n };\n\n this.formatDate = function(date, format, lang, timezone){\n return dateFilter(date, format, timezone);\n };\n\n });\n\n// Source: helpers/date-parser.js\nangular.module('mgcrea.ngStrap.helpers.dateParser', [])\n\n.provider('$dateParser', function($localeProvider) {\n\n // define a custom ParseDate object to use instead of native Date\n // to avoid date values wrapping when setting date component values\n function ParseDate() {\n this.year = 1970;\n this.month = 0;\n this.day = 1;\n this.hours = 0;\n this.minutes = 0;\n this.seconds = 0;\n this.milliseconds = 0;\n }\n\n ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };\n ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };\n ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };\n ParseDate.prototype.setHours = function(value) { this.hours = value; };\n ParseDate.prototype.getHours = function() { return this.hours; };\n ParseDate.prototype.setDate = function(value) { this.day = value; };\n ParseDate.prototype.setMonth = function(value) { this.month = value; };\n ParseDate.prototype.setFullYear = function(value) { this.year = value; };\n ParseDate.prototype.fromDate = function(value) {\n this.year = value.getFullYear();\n this.month = value.getMonth();\n this.day = value.getDate();\n this.hours = value.getHours();\n this.minutes = value.getMinutes();\n this.seconds = value.getSeconds();\n this.milliseconds = value.getMilliseconds();\n return this;\n };\n\n ParseDate.prototype.toDate = function() {\n return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n };\n\n var proto = ParseDate.prototype;\n\n function noop() {\n }\n\n function isNumeric(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n function indexOfCaseInsensitive(array, value) {\n var len = array.length, str=value.toString().toLowerCase();\n for (var i=0; i<len; i++) {\n if (array[i].toLowerCase() === str) { return i; }\n }\n return -1; // Return -1 per the \"Array.indexOf()\" method.\n }\n\n var defaults = this.defaults = {\n format: 'shortDate',\n strict: false\n };\n\n this.$get = function($locale, dateFilter) {\n\n var DateParserFactory = function(config) {\n\n var options = angular.extend({}, defaults, config);\n\n var $dateParser = {};\n\n var regExpMap = {\n 'sss' : '[0-9]{3}',\n 'ss' : '[0-5][0-9]',\n 's' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n 'mm' : '[0-5][0-9]',\n 'm' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n 'HH' : '[01][0-9]|2[0-3]',\n 'H' : options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]',\n 'hh' : '[0][1-9]|[1][012]',\n 'h' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n 'a' : 'AM|PM',\n 'EEEE' : $locale.DATETIME_FORMATS.DAY.join('|'),\n 'EEE' : $locale.DATETIME_FORMATS.SHORTDAY.join('|'),\n 'dd' : '0[1-9]|[12][0-9]|3[01]',\n 'd' : options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]',\n 'MMMM' : $locale.DATETIME_FORMATS.MONTH.join('|'),\n 'MMM' : $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n 'MM' : '0[1-9]|1[012]',\n 'M' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n 'yyyy' : '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',\n 'yy' : '[0-9]{2}',\n 'y' : options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}',\n };\n\n var setFnMap = {\n 'sss' : proto.setMilliseconds,\n 'ss' : proto.setSeconds,\n 's' : proto.setSeconds,\n 'mm' : proto.setMinutes,\n 'm' : proto.setMinutes,\n 'HH' : proto.setHours,\n 'H' : proto.setHours,\n 'hh' : proto.setHours,\n 'h' : proto.setHours,\n 'EEEE' : noop,\n 'EEE' : noop,\n 'dd' : proto.setDate,\n 'd' : proto.setDate,\n 'a' : function(value) { var hours = this.getHours() % 12; return this.setHours(value.match(/pm/i) ? hours + 12 : hours); },\n 'MMMM' : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.MONTH, value)); },\n 'MMM' : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.SHORTMONTH, value)); },\n 'MM' : function(value) { return this.setMonth(1 * value - 1); },\n 'M' : function(value) { return this.setMonth(1 * value - 1); },\n 'yyyy' : proto.setFullYear,\n 'yy' : function(value) { return this.setFullYear(2000 + 1 * value); },\n 'y' : proto.setFullYear\n };\n\n var regex, setMap;\n\n $dateParser.init = function() {\n $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;\n regex = regExpForFormat($dateParser.$format);\n setMap = setMapForFormat($dateParser.$format);\n };\n\n $dateParser.isValid = function(date) {\n if(angular.isDate(date)) return !isNaN(date.getTime());\n return regex.test(date);\n };\n\n $dateParser.parse = function(value, baseDate, format, timezone) {\n // check for date format special names\n if(format) format = $locale.DATETIME_FORMATS[format] || format;\n if(angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format, timezone);\n var formatRegex = format ? regExpForFormat(format) : regex;\n var formatSetMap = format ? setMapForFormat(format) : setMap;\n var matches = formatRegex.exec(value);\n if(!matches) return false;\n // use custom ParseDate object to set parsed values\n var date = baseDate && !isNaN(baseDate.getTime()) ? new ParseDate().fromDate(baseDate) : new ParseDate().fromDate(new Date(1970, 0, 1, 0));\n for(var i = 0; i < matches.length - 1; i++) {\n formatSetMap[i] && formatSetMap[i].call(date, matches[i+1]);\n }\n // convert back to native Date object\n var newDate = date.toDate();\n\n // check new native Date object for day values overflow\n if (parseInt(date.day, 10) !== newDate.getDate()) {\n return false;\n }\n\n return newDate;\n };\n\n $dateParser.getDateForAttribute = function(key, value) {\n var date;\n\n if(value === 'today') {\n var today = new Date();\n date = new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, (key === 'minDate' ? 0 : -1));\n } else if(angular.isString(value) && value.match(/^\".+\"$/)) { // Support {{ dateObj }}\n date = new Date(value.substr(1, value.length - 2));\n } else if(isNumeric(value)) {\n date = new Date(parseInt(value, 10));\n } else if (angular.isString(value) && 0 === value.length) { // Reset date\n date = key === 'minDate' ? -Infinity : +Infinity;\n } else {\n date = new Date(value);\n }\n\n return date;\n };\n\n $dateParser.getTimeForAttribute = function(key, value) {\n var time;\n\n if(value === 'now') {\n time = new Date().setFullYear(1970, 0, 1);\n } else if(angular.isString(value) && value.match(/^\".+\"$/)) {\n time = new Date(value.substr(1, value.length - 2)).setFullYear(1970, 0, 1);\n } else if(isNumeric(value)) {\n time = new Date(parseInt(value, 10)).setFullYear(1970, 0, 1);\n } else if (angular.isString(value) && 0 === value.length) { // Reset time\n time = key === 'minTime' ? -Infinity : +Infinity;\n } else {\n time = $dateParser.parse(value, new Date(1970, 0, 1, 0));\n }\n\n return time;\n };\n\n /* Handle switch to/from daylight saving.\n * Hours may be non-zero on daylight saving cut-over:\n * > 12 when midnight changeover, but then cannot generate\n * midnight datetime, so jump to 1AM, otherwise reset.\n * @param date (Date) the date to check\n * @return (Date) the corrected date\n *\n * __ copied from jquery ui datepicker __\n */\n $dateParser.daylightSavingAdjust = function(date) {\n if (!date) {\n return null;\n }\n date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n return date;\n };\n\n /* Correct the date for timezone offset.\n * @param date (Date) the date to adjust\n * @param timezone (string) the timezone to adjust for\n * @param undo (boolean) to add or subtract timezone offset\n * @return (Date) the corrected date\n */\n $dateParser.timezoneOffsetAdjust = function(date, timezone, undo) {\n if (!date) {\n return null;\n }\n // Right now, only 'UTC' is supported.\n if (timezone && timezone === 'UTC') {\n date = new Date(date.getTime());\n date.setMinutes(date.getMinutes() + (undo?-1:1)*date.getTimezoneOffset());\n }\n return date;\n };\n\n // Private functions\n\n function setMapForFormat(format) {\n var keys = Object.keys(setFnMap), i;\n var map = [], sortedMap = [];\n // Map to setFn\n var clonedFormat = format;\n for(i = 0; i < keys.length; i++) {\n if(format.split(keys[i]).length > 1) {\n var index = clonedFormat.search(keys[i]);\n format = format.split(keys[i]).join('');\n if(setFnMap[keys[i]]) {\n map[index] = setFnMap[keys[i]];\n }\n }\n }\n // Sort result map\n angular.forEach(map, function(v) {\n // conditional required since angular.forEach broke around v1.2.21\n // related pr: https://github.com/angular/angular.js/pull/8525\n if(v) sortedMap.push(v);\n });\n return sortedMap;\n }\n\n function escapeReservedSymbols(text) {\n return text.replace(/\\//g, '[\\\\/]').replace('/-/g', '[-]').replace(/\\./g, '[.]').replace(/\\\\s/g, '[\\\\s]');\n }\n\n function regExpForFormat(format) {\n var keys = Object.keys(regExpMap), i;\n\n var re = format;\n // Abstract replaces to avoid collisions\n for(i = 0; i < keys.length; i++) {\n re = re.split(keys[i]).join('${' + i + '}');\n }\n // Replace abstracted values\n for(i = 0; i < keys.length; i++) {\n re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');\n }\n format = escapeReservedSymbols(format);\n\n return new RegExp('^' + re + '$', ['i']);\n }\n\n $dateParser.init();\n return $dateParser;\n\n };\n\n return DateParserFactory;\n\n };\n\n});\n\n// Source: helpers/debounce.js\nangular.module('mgcrea.ngStrap.helpers.debounce', [])\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L693\n.factory('debounce', function($timeout) {\n return function(func, wait, immediate) {\n var timeout = null;\n return function() {\n var context = this,\n args = arguments,\n callNow = immediate && !timeout;\n if(timeout) {\n $timeout.cancel(timeout);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(!immediate) {\n func.apply(context, args);\n }\n }, wait, false);\n if(callNow) {\n func.apply(context, args);\n }\n return timeout;\n };\n };\n})\n\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L661\n.factory('throttle', function($timeout) {\n return function(func, wait, options) {\n var timeout = null;\n options || (options = {});\n return function() {\n var context = this,\n args = arguments;\n if(!timeout) {\n if(options.leading !== false) {\n func.apply(context, args);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(options.trailing !== false) {\n func.apply(context, args);\n }\n }, wait, false);\n }\n };\n };\n});\n\n// Source: helpers/dimensions.js\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n .factory('dimensions', function($document, $window) {\n\n var jqLite = angular.element;\n var fn = {};\n\n /**\n * Test the element nodeName\n * @param element\n * @param name\n */\n var nodeName = fn.nodeName = function(element, name) {\n return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();\n };\n\n /**\n * Returns the element computed style\n * @param element\n * @param prop\n * @param extra\n */\n fn.css = function(element, prop, extra) {\n var value;\n if (element.currentStyle) { //IE\n value = element.currentStyle[prop];\n } else if (window.getComputedStyle) {\n value = window.getComputedStyle(element)[prop];\n } else {\n value = element.style[prop];\n }\n return extra === true ? parseFloat(value) || 0 : value;\n };\n\n /**\n * Provides read-only equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.offset = function(element) {\n var boxRect = element.getBoundingClientRect();\n var docElement = element.ownerDocument;\n return {\n width: boxRect.width || element.offsetWidth,\n height: boxRect.height || element.offsetHeight,\n top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),\n left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)\n };\n };\n \n /**\n * Provides set equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip\n * @url http://api.jquery.com/offset/\n * @param element\n * @param options\n * @param i\n */\n fn.setOffset = function (element, options, i) {\n var curPosition,\n curLeft,\n curCSSTop,\n curTop,\n curOffset,\n curCSSLeft,\n calculatePosition,\n position = fn.css(element, 'position'),\n curElem = angular.element(element),\n props = {};\n \n // Set position first, in-case top/left are set even on static elem\n if (position === 'static') {\n element.style.position = 'relative';\n }\n \n curOffset = fn.offset(element);\n curCSSTop = fn.css(element, 'top');\n curCSSLeft = fn.css(element, 'left');\n calculatePosition = (position === 'absolute' || position === 'fixed') && \n (curCSSTop + curCSSLeft).indexOf('auto') > -1;\n \n // Need to be able to calculate position if either\n // top or left is auto and position is either absolute or fixed\n if (calculatePosition) {\n curPosition = fn.position(element);\n curTop = curPosition.top;\n curLeft = curPosition.left;\n } else {\n curTop = parseFloat(curCSSTop) || 0;\n curLeft = parseFloat(curCSSLeft) || 0;\n }\n \n if (angular.isFunction(options)) {\n options = options.call(element, i, curOffset);\n }\n \n if (options.top !== null ) {\n props.top = (options.top - curOffset.top) + curTop;\n }\n if ( options.left !== null ) {\n props.left = (options.left - curOffset.left) + curLeft;\n }\n\n if ('using' in options) {\n options.using.call(curElem, props);\n } else {\n curElem.css({\n top: props.top + 'px',\n left: props.left + 'px'\n });\n }\n };\n\n /**\n * Provides read-only equivalent of jQuery's position function\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.position = function(element) {\n\n var offsetParentRect = {top: 0, left: 0},\n offsetParentElement,\n offset;\n\n // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n if (fn.css(element, 'position') === 'fixed') {\n\n // We assume that getBoundingClientRect is available when computed position is fixed\n offset = element.getBoundingClientRect();\n\n } else {\n\n // Get *real* offsetParentElement\n offsetParentElement = offsetParent(element);\n\n // Get correct offsets\n offset = fn.offset(element);\n if (!nodeName(offsetParentElement, 'html')) {\n offsetParentRect = fn.offset(offsetParentElement);\n }\n\n // Add offsetParent borders\n offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);\n offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);\n }\n\n // Subtract parent offsets and element margins\n return {\n width: element.offsetWidth,\n height: element.offsetHeight,\n top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),\n left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)\n };\n\n };\n\n /**\n * Returns the closest, non-statically positioned offsetParent of a given element\n * @required-by fn.position\n * @param element\n */\n var offsetParent = function offsetParentElement(element) {\n var docElement = element.ownerDocument;\n var offsetParent = element.offsetParent || docElement;\n if(nodeName(offsetParent, '#document')) return docElement.documentElement;\n while(offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {\n offsetParent = offsetParent.offsetParent;\n }\n return offsetParent || docElement.documentElement;\n };\n\n /**\n * Provides equivalent of jQuery's height function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/height/\n * @param element\n * @param outer\n */\n fn.height = function(element, outer) {\n var value = element.offsetHeight;\n if(outer) {\n value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);\n } else {\n value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);\n }\n return value;\n };\n\n /**\n * Provides equivalent of jQuery's width function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/width/\n * @param element\n * @param outer\n */\n fn.width = function(element, outer) {\n var value = element.offsetWidth;\n if(outer) {\n value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);\n } else {\n value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);\n }\n return value;\n };\n\n return fn;\n\n });\n\n// Source: helpers/parse-options.js\nangular.module('mgcrea.ngStrap.helpers.parseOptions', [])\n\n .provider('$parseOptions', function() {\n\n var defaults = this.defaults = {\n 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+(.*?))?$/\n };\n\n this.$get = function($parse, $q) {\n\n function ParseOptionsFactory(attr, config) {\n\n var $parseOptions = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n $parseOptions.$values = [];\n\n // Private vars\n var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;\n\n $parseOptions.init = function() {\n $parseOptions.$match = match = attr.match(options.regexp);\n displayFn = $parse(match[2] || match[1]),\n valueName = match[4] || match[6],\n keyName = match[5],\n groupByFn = $parse(match[3] || ''),\n valueFn = $parse(match[2] ? match[1] : valueName),\n valuesFn = $parse(match[7]);\n };\n\n $parseOptions.valuesFn = function(scope, controller) {\n return $q.when(valuesFn(scope, controller))\n .then(function(values) {\n $parseOptions.$values = values ? parseValues(values, scope) : {};\n return $parseOptions.$values;\n });\n };\n\n $parseOptions.displayValue = function(modelValue) {\n var scope = {};\n scope[valueName] = modelValue;\n return displayFn(scope);\n };\n\n // Private functions\n\n function parseValues(values, scope) {\n return values.map(function(match, index) {\n var locals = {}, label, value;\n locals[valueName] = match;\n label = displayFn(scope, locals);\n value = valueFn(scope, locals);\n return {label: label, value: value, index: index};\n });\n }\n\n $parseOptions.init();\n return $parseOptions;\n\n }\n\n return ParseOptionsFactory;\n\n };\n\n });\n\n// Source: helpers/raf.js\n(angular.version.minor < 3 && angular.version.dot < 14) && angular.module('ng')\n\n.factory('$$rAF', function($window, $timeout) {\n\n var requestAnimationFrame = $window.requestAnimationFrame ||\n $window.webkitRequestAnimationFrame ||\n $window.mozRequestAnimationFrame;\n\n var cancelAnimationFrame = $window.cancelAnimationFrame ||\n $window.webkitCancelAnimationFrame ||\n $window.mozCancelAnimationFrame ||\n $window.webkitCancelRequestAnimationFrame;\n\n var rafSupported = !!requestAnimationFrame;\n var raf = rafSupported ?\n function(fn) {\n var id = requestAnimationFrame(fn);\n return function() {\n cancelAnimationFrame(id);\n };\n } :\n function(fn) {\n var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n return function() {\n $timeout.cancel(timer);\n };\n };\n\n raf.supported = rafSupported;\n\n return raf;\n\n});\n\n// .factory('$$animateReflow', function($$rAF, $document) {\n\n// var bodyEl = $document[0].body;\n\n// return function(fn) {\n// //the returned function acts as the cancellation function\n// return $$rAF(function() {\n// //the line below will force the browser to perform a repaint\n// //so that all the animated elements within the animation frame\n// //will be properly updated and drawn on screen. This is\n// //required to perform multi-class CSS based animations with\n// //Firefox. DO NOT REMOVE THIS LINE.\n// var a = bodyEl.offsetWidth + 1;\n// fn();\n// });\n// };\n\n// });\n\n// Source: modal/modal.js\nangular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$modal', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n backdropAnimation: 'am-fade',\n prefixClass: 'modal',\n prefixEvent: 'modal',\n placement: 'top',\n template: 'modal/modal.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {\n\n var forEach = angular.forEach;\n var trim = String.prototype.trim;\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n var bodyElement = angular.element($window.document.body);\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n\n function ModalFactory(config) {\n\n var $modal = {};\n\n // Common vars\n var options = $modal.$options = angular.extend({}, defaults, config);\n $modal.$promise = fetchTemplate(options.template);\n var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(!options.element && !options.container) {\n options.container = 'body';\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $modal.$id = options.id || options.element && options.element.attr('id') || '';\n\n // Support scope as string options\n forEach(['title', 'content'], function(key) {\n if(options[key]) scope[key] = $sce.trustAsHtml(options[key]);\n });\n\n // Provide scope helpers\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $modal.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $modal.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $modal.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $modal.$isShown = scope.$isShown = false;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $modal.$promise = $modal.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);\n // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n if(!config.template) contentEl.next().remove();\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize modal\n var modalLinker, modalElement;\n var backdropElement = angular.element('<div class=\"' + options.prefixClass + '-backdrop\"/>');\n backdropElement.css({position:'fixed', top:'0px', left:'0px', bottom:'0px', right:'0px', 'z-index': 1038});\n $modal.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n modalLinker = $compile(template);\n $modal.init();\n });\n\n $modal.init = function() {\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n $modal.show();\n });\n }\n\n };\n\n $modal.destroy = function() {\n\n // Remove element\n if(modalElement) {\n modalElement.remove();\n modalElement = null;\n }\n if(backdropElement) {\n backdropElement.remove();\n backdropElement = null;\n }\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $modal.show = function() {\n if($modal.$isShown) return;\n\n var parent, after;\n if(angular.isElement(options.container)) {\n parent = options.container;\n after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;\n } else {\n if (options.container) {\n parent = findElement(options.container);\n after = parent[0] && parent[0].lastChild ? angular.element(parent[0].lastChild) : null;\n } else {\n parent = null;\n after = options.element;\n }\n }\n\n // Fetch a cloned element linked from template\n modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\n\n if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n return;\n }\n\n // Set the initial positioning.\n modalElement.css({display: 'block'}).addClass(options.placement);\n\n // Options: animation\n if(options.animation) {\n if(options.backdrop) {\n backdropElement.addClass(options.backdropAnimation);\n }\n modalElement.addClass(options.animation);\n }\n\n if(options.backdrop) {\n $animate.enter(backdropElement, bodyElement, null);\n }\n\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if(angular.version.minor <= 2) {\n $animate.enter(modalElement, parent, after, enterAnimateCallback);\n } else {\n $animate.enter(modalElement, parent, after).then(enterAnimateCallback);\n }\n\n $modal.$isShown = scope.$isShown = true;\n safeDigest(scope);\n // Focus once the enter-animation has started\n // Weird PhantomJS bug hack\n var el = modalElement[0];\n requestAnimationFrame(function() {\n el.focus();\n });\n\n bodyElement.addClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n }\n\n // Bind events\n if(options.backdrop) {\n modalElement.on('click', hideOnBackdropClick);\n backdropElement.on('click', hideOnBackdropClick);\n backdropElement.on('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.on('keyup', $modal.$onKeyUp);\n }\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $modal);\n }\n\n $modal.hide = function() {\n if(!$modal.$isShown) return;\n\n if(scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {\n return;\n }\n\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if(angular.version.minor <= 2) {\n $animate.leave(modalElement, leaveAnimateCallback);\n } else {\n $animate.leave(modalElement).then(leaveAnimateCallback);\n }\n\n if(options.backdrop) {\n $animate.leave(backdropElement);\n }\n $modal.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.backdrop) {\n modalElement.off('click', hideOnBackdropClick);\n backdropElement.off('click', hideOnBackdropClick);\n backdropElement.off('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.off('keyup', $modal.$onKeyUp);\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $modal);\n bodyElement.removeClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n }\n }\n\n $modal.toggle = function() {\n\n $modal.$isShown ? $modal.hide() : $modal.show();\n\n };\n\n $modal.focus = function() {\n modalElement[0].focus();\n };\n\n // Protected methods\n\n $modal.$onKeyUp = function(evt) {\n\n if (evt.which === 27 && $modal.$isShown) {\n $modal.hide();\n evt.stopPropagation();\n }\n\n };\n\n // Private methods\n\n function hideOnBackdropClick(evt) {\n if(evt.target !== evt.currentTarget) return;\n options.backdrop === 'static' ? $modal.focus() : $modal.hide();\n }\n\n function preventEventDefault(evt) {\n evt.preventDefault();\n }\n\n return $modal;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return ModalFactory;\n\n };\n\n })\n\n .directive('bsModal', function($window, $sce, $modal) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsModal && scope.$watch(attr.bsModal, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize modal\n var modal = $modal(options);\n\n // Trigger\n element.on(attr.trigger || 'click', modal.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (modal) modal.destroy();\n options = null;\n modal = null;\n });\n\n }\n };\n\n });\n\n// Source: navbar/navbar.js\nangular.module('mgcrea.ngStrap.navbar', [])\n\n .provider('$navbar', function() {\n\n var defaults = this.defaults = {\n activeClass: 'active',\n routeAttr: 'data-match-route',\n strict: false\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsNavbar', function($window, $location, $navbar) {\n\n var defaults = $navbar.defaults;\n\n return {\n restrict: 'A',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = angular.copy(defaults);\n angular.forEach(Object.keys(defaults), function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Watch for the $location\n scope.$watch(function() {\n\n return $location.path();\n\n }, function(newValue, oldValue) {\n\n var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');\n\n angular.forEach(liElements, function(li) {\n\n var liElement = angular.element(li);\n var pattern = liElement.attr(options.routeAttr).replace('/', '\\\\/');\n if(options.strict) {\n pattern = '^' + pattern + '$';\n }\n var regexp = new RegExp(pattern, 'i');\n\n if(regexp.test(newValue)) {\n liElement.addClass(options.activeClass);\n } else {\n liElement.removeClass(options.activeClass);\n }\n\n });\n\n });\n\n }\n\n };\n\n });\n\n// Source: popover/popover.js\nangular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$popover', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n // uncommenting the next two lines will break backwards compatability\n // prefixClass: 'popover',\n // prefixEvent: 'popover',\n container: false,\n target: false,\n placement: 'right',\n template: 'popover/popover.tpl.html',\n contentTemplate: false,\n trigger: 'click',\n keyboard: true,\n html: false,\n title: '',\n content: '',\n delay: 0,\n autoClose: false\n };\n\n this.$get = function($tooltip) {\n\n function PopoverFactory(element, config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n var $popover = $tooltip(element, options);\n\n // Support scope as string options [/*title, */content]\n if(options.content) {\n $popover.$scope.content = options.content;\n }\n\n return $popover;\n\n }\n\n return PopoverFactory;\n\n };\n\n })\n\n .directive('bsPopover', function($window, $sce, $popover) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'customClass', 'autoClose', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoClose'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n });\n });\n\n // Support scope as an object\n attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);\n newValue === true ? popover.show() : popover.hide();\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n popover.setViewport(newValue);\n });\n\n // Initialize popover\n var popover = $popover(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (popover) popover.destroy();\n options = null;\n popover = null;\n });\n\n }\n };\n\n });\n\n// Source: scrollspy/scrollspy.js\nangular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', 'mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$scrollspy', function() {\n\n // Pool of registered spies\n var spies = this.$$spies = {};\n\n var defaults = this.defaults = {\n debounce: 150,\n throttle: 100,\n offset: 100\n };\n\n this.$get = function($window, $document, $rootScope, dimensions, debounce, throttle) {\n\n var windowEl = angular.element($window);\n var docEl = angular.element($document.prop('documentElement'));\n var bodyEl = angular.element($window.document.body);\n\n // Helper functions\n\n function nodeName(element, name) {\n return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();\n }\n\n function ScrollSpyFactory(config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n if(!options.element) options.element = bodyEl;\n var isWindowSpy = nodeName(options.element, 'body');\n var scrollEl = isWindowSpy ? windowEl : options.element;\n var scrollId = isWindowSpy ? 'window' : options.id;\n\n // Use existing spy\n if(spies[scrollId]) {\n spies[scrollId].$$count++;\n return spies[scrollId];\n }\n\n var $scrollspy = {};\n\n // Private vars\n var unbindViewContentLoaded, unbindIncludeContentLoaded;\n var trackedElements = $scrollspy.$trackedElements = [];\n var sortedElements = [];\n var activeTarget;\n var debouncedCheckPosition;\n var throttledCheckPosition;\n var debouncedCheckOffsets;\n var viewportHeight;\n var scrollTop;\n\n $scrollspy.init = function() {\n\n // Setup internal ref counter\n this.$$count = 1;\n\n // Bind events\n debouncedCheckPosition = debounce(this.checkPosition, options.debounce);\n throttledCheckPosition = throttle(this.checkPosition, options.throttle);\n scrollEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', debouncedCheckPosition);\n scrollEl.on('scroll', throttledCheckPosition);\n\n debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);\n unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);\n unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);\n debouncedCheckOffsets();\n\n // Register spy for reuse\n if(scrollId) {\n spies[scrollId] = $scrollspy;\n }\n\n };\n\n $scrollspy.destroy = function() {\n\n // Check internal ref counter\n this.$$count--;\n if(this.$$count > 0) {\n return;\n }\n\n // Unbind events\n scrollEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', debouncedCheckPosition);\n scrollEl.off('scroll', throttledCheckPosition);\n unbindViewContentLoaded();\n unbindIncludeContentLoaded();\n if (scrollId) {\n delete spies[scrollId];\n }\n };\n\n $scrollspy.checkPosition = function() {\n\n // Not ready yet\n if(!sortedElements.length) return;\n\n // Calculate the scroll position\n scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;\n\n // Calculate the viewport height for use by the components\n viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));\n\n // Activate first element if scroll is smaller\n if(scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {\n return $scrollspy.$activateElement(sortedElements[0]);\n }\n\n // Activate proper element\n for (var i = sortedElements.length; i--;) {\n if(angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) continue;\n if(activeTarget === sortedElements[i].target) continue;\n if(scrollTop < sortedElements[i].offsetTop) continue;\n if(sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) continue;\n return $scrollspy.$activateElement(sortedElements[i]);\n }\n\n };\n\n $scrollspy.checkPositionWithEventLoop = function() {\n // IE 9 throws an error if we use 'this' instead of '$scrollspy'\n // in this setTimeout call\n setTimeout($scrollspy.checkPosition, 1);\n };\n\n // Protected methods\n\n $scrollspy.$activateElement = function(element) {\n if(activeTarget) {\n var activeElement = $scrollspy.$getTrackedElement(activeTarget);\n if(activeElement) {\n activeElement.source.removeClass('active');\n if(nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {\n activeElement.source.parent().parent().removeClass('active');\n }\n }\n }\n activeTarget = element.target;\n element.source.addClass('active');\n if(nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {\n element.source.parent().parent().addClass('active');\n }\n };\n\n $scrollspy.$getTrackedElement = function(target) {\n return trackedElements.filter(function(obj) {\n return obj.target === target;\n })[0];\n };\n\n // Track offsets behavior\n\n $scrollspy.checkOffsets = function() {\n\n angular.forEach(trackedElements, function(trackedElement) {\n var targetElement = document.querySelector(trackedElement.target);\n trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;\n if(options.offset && trackedElement.offsetTop !== null) trackedElement.offsetTop -= options.offset * 1;\n });\n\n sortedElements = trackedElements\n .filter(function(el) {\n return el.offsetTop !== null;\n })\n .sort(function(a, b) {\n return a.offsetTop - b.offsetTop;\n });\n\n debouncedCheckPosition();\n\n };\n\n $scrollspy.trackElement = function(target, source) {\n trackedElements.push({target: target, source: source});\n };\n\n $scrollspy.untrackElement = function(target, source) {\n var toDelete;\n for (var i = trackedElements.length; i--;) {\n if(trackedElements[i].target === target && trackedElements[i].source === source) {\n toDelete = i;\n break;\n }\n }\n trackedElements = trackedElements.splice(toDelete, 1);\n };\n\n $scrollspy.activate = function(i) {\n trackedElements[i].addClass('active');\n };\n\n // Initialize plugin\n\n $scrollspy.init();\n return $scrollspy;\n\n }\n\n return ScrollSpyFactory;\n\n };\n\n })\n\n .directive('bsScrollspy', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'EAC',\n link: function postLink(scope, element, attr) {\n\n var options = {scope: scope};\n angular.forEach(['offset', 'target'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n var scrollspy = $scrollspy(options);\n scrollspy.trackElement(options.target, element);\n\n scope.$on('$destroy', function() {\n if (scrollspy) {\n scrollspy.untrackElement(options.target, element);\n scrollspy.destroy();\n }\n options = null;\n scrollspy = null;\n });\n\n }\n };\n\n })\n\n\n .directive('bsScrollspyList', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'A',\n compile: function postLink(element, attr) {\n var children = element[0].querySelectorAll('li > a[href]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));\n });\n }\n\n };\n\n });\n\n// Source: select/select.js\nangular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$select', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'select',\n prefixEvent: '$select',\n placement: 'bottom-left',\n template: 'select/select.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n multiple: false,\n allNoneButtons: false,\n sort: true,\n caretHtml: '&nbsp;<span class=\"caret\"></span>',\n placeholder: 'Choose among the following...',\n allText: 'All',\n noneText: 'None',\n maxLength: 3,\n maxLengthHtml: 'selected',\n iconCheckmark: 'glyphicon glyphicon-ok'\n };\n\n this.$get = function($window, $document, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n\n function SelectFactory(element, controller, config) {\n\n var $select = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $select = $tooltip(element, options);\n var scope = $select.$scope;\n\n scope.$matches = [];\n if (options.multiple) {\n scope.$activeIndex = [];\n }\n else {\n scope.$activeIndex = -1;\n }\n scope.$isMultiple = options.multiple;\n scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n scope.$iconCheckmark = options.iconCheckmark;\n scope.$allText = options.allText;\n scope.$noneText = options.noneText;\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $select.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $select.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $select.$isVisible();\n };\n\n scope.$isActive = function(index) {\n return $select.$isActive(index);\n };\n\n scope.$selectAll = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (!scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n scope.$selectNone = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n // Public methods\n\n $select.update = function(matches) {\n scope.$matches = matches;\n $select.$updateActiveIndex();\n };\n\n $select.activate = function(index) {\n if(options.multiple) {\n $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);\n if(options.sort) scope.$activeIndex.sort(function(a, b) { return a - b; }); // use numeric sort instead of default sort\n } else {\n scope.$activeIndex = index;\n }\n return scope.$activeIndex;\n };\n\n $select.select = function(index) {\n var value = scope.$matches[index].value;\n scope.$apply(function() {\n $select.activate(index);\n if(options.multiple) {\n controller.$setViewValue(scope.$activeIndex.map(function(index) {\n return scope.$matches[index].value;\n }));\n } else {\n controller.$setViewValue(value);\n // Hide if single select\n $select.hide();\n }\n });\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $select);\n };\n\n // Protected methods\n\n $select.$updateActiveIndex = function() {\n if(controller.$modelValue && scope.$matches.length) {\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n scope.$activeIndex = controller.$modelValue.map(function(value) {\n return $select.$getIndex(value);\n });\n } else {\n scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n }\n } else if(scope.$activeIndex >= scope.$matches.length) {\n scope.$activeIndex = options.multiple ? [] : 0;\n }\n };\n\n $select.$isVisible = function() {\n if(!options.minLength || !controller) {\n return scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && controller.$viewValue.length >= options.minLength;\n };\n\n $select.$isActive = function(index) {\n if(options.multiple) {\n return scope.$activeIndex.indexOf(index) !== -1;\n } else {\n return scope.$activeIndex === index;\n }\n };\n\n $select.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $select.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n targetEl.triggerHandler('click');\n }\n };\n\n $select.$onKeyDown = function(evt) {\n if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // release focus on tab\n if (options.multiple && evt.keyCode === 9) {\n return $select.hide();\n }\n\n // Select with enter\n if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n return $select.select(scope.$activeIndex);\n }\n\n if (!options.multiple) {\n // Navigate with keyboard\n if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 38 && scope.$activeIndex < 0) scope.$activeIndex = scope.$matches.length - 1;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n }\n };\n\n // Overrides\n\n var _show = $select.show;\n $select.show = function() {\n _show();\n if(options.multiple) {\n $select.$element.addClass('select-multiple');\n }\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $select.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $select.hide;\n $select.hide = function() {\n if(!options.multiple && !controller.$modelValue) {\n scope.$activeIndex = -1;\n }\n $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $select.$onKeyDown);\n }\n _hide(true);\n };\n\n return $select;\n\n }\n\n SelectFactory.defaults = defaults;\n return SelectFactory;\n\n };\n\n })\n\n .directive('bsSelect', function($window, $parse, $q, $select, $parseOptions) {\n\n var defaults = $select.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, placeholder: defaults.placeholder};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'placeholder', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id', 'sort', 'caretHtml', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'allNoneButtons', 'sort'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Only parse data-multiple. Angular sets existence attributes to true (multiple/required/etc), they apply this\n // to data-multiple as well for some reason, so we'll parse this ourselves and disregard multiple\n var dataMultiple = element.attr('data-multiple');\n if(angular.isDefined(dataMultiple)) {\n if(falseValueRegExp.test(dataMultiple))\n options.multiple = false;\n else\n options.multiple = dataMultiple;\n }\n\n // Add support for select markup\n if(element[0].nodeName.toLowerCase() === 'select') {\n var inputEl = element;\n inputEl.css('display', 'none');\n element = angular.element('<button type=\"button\" class=\"btn btn-default\"></button>');\n inputEl.after(element);\n }\n\n // Build proper bsOptions\n var parsedOptions = $parseOptions(attr.bsOptions);\n\n // Initialize select\n var select = $select(element, controller, options);\n\n // Watch bsOptions values before filtering for changes\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n scope.$watchCollection(watchedOptions, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n select.update(values);\n controller.$render();\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n select.$updateActiveIndex();\n controller.$render();\n }, true);\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var selected, index;\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n selected = controller.$modelValue.map(function(value) {\n index = select.$getIndex(value);\n return angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }).filter(angular.isDefined);\n if(selected.length > (options.maxLength || defaults.maxLength)) {\n selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml);\n } else {\n selected = selected.join(', ');\n }\n } else {\n index = select.$getIndex(controller.$modelValue);\n selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }\n element.html((selected ? selected : options.placeholder) + (options.caretHtml ? options.caretHtml : defaults.caretHtml));\n };\n\n if(options.multiple){\n controller.$isEmpty = function(value){\n return !value || value.length === 0;\n };\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (select) select.destroy();\n options = null;\n select = null;\n });\n\n }\n };\n\n });\n\n// Source: tab/tab.js\nangular.module('mgcrea.ngStrap.tab', [])\n\n .provider('$tab', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n template: 'tab/tab.tpl.html',\n navClass: 'nav-tabs',\n activeClass: 'active'\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'navClass', 'activeClass'], function(key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // Publish options on scope\n $scope.$navClass = self.$options.navClass;\n $scope.$activeClass = self.$options.activeClass;\n\n self.$panes = $scope.$panes = [];\n\n // Please use $activePaneChangeListeners if you use `bsActivePane`\n // Because we removed `ngModel` as default, we rename viewChangeListeners to\n // activePaneChangeListeners to make more sense.\n self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n if(angular.isUndefined(self.$panes.$active)) {\n $scope.$setActive(pane.name || 0);\n }\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var active = self.$panes.$active;\n var activeIndex;\n if(angular.isString(active)) {\n activeIndex = self.$panes.map(function(pane) {\n return pane.name;\n }).indexOf(active);\n } else {\n activeIndex = self.$panes.$active;\n }\n\n // remove pane from $panes array\n self.$panes.splice(index, 1);\n\n if (index < activeIndex) {\n // we removed a pane before the active pane, so we need to\n // decrement the active pane index\n activeIndex--;\n }\n else if (index === activeIndex && activeIndex === self.$panes.length) {\n // we remove the active pane and it was the one at the end,\n // so select the previous one\n activeIndex--;\n }\n if(activeIndex >= 0 && activeIndex < self.$panes.length) {\n self.$setActive(self.$panes[activeIndex].name || activeIndex);\n } else {\n self.$setActive();\n }\n };\n\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$activePaneChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$isActive = $scope.$isActive = function($pane, $index) {\n return self.$panes.$active === $pane.name || self.$panes.$active === $index;\n };\n\n };\n\n this.$get = function() {\n var $tab = {};\n $tab.defaults = defaults;\n $tab.controller = controller;\n return $tab;\n };\n\n })\n\n .directive('bsTabs', function($window, $animate, $tab, $parse) {\n\n var defaults = $tab.defaults;\n\n return {\n require: ['?ngModel', 'bsTabs'],\n transclude: true,\n scope: true,\n controller: ['$scope', '$element', '$attrs', $tab.controller],\n templateUrl: function(element, attr) {\n return attr.template || defaults.template;\n },\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // 'ngModel' does interfere with form validation\n // and status, use `bsActivePane` instead to avoid it\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n bsTabsCtrl.$setActive(modelValue);\n return modelValue;\n });\n\n }\n\n if (attrs.bsActivePane) {\n // adapted from angularjs ngModelController bindings\n // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n // Update bsActivePane value with change\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n });\n\n // watch bsActivePane for value changes\n scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n bsTabsCtrl.$setActive(newValue);\n }, true);\n }\n }\n };\n\n })\n\n .directive('bsPane', function($window, $animate, $sce) {\n\n return {\n require: ['^?ngModel', '^bsTabs'],\n scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // Add base class\n element.addClass('tab-pane');\n\n // Observe title attribute for change\n attrs.$observe('title', function(newValue, oldValue) {\n scope.title = $sce.trustAsHtml(newValue);\n });\n\n // Save tab name into scope\n scope.name = attrs.name;\n\n // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\n }\n\n attrs.$observe('disabled', function(newValue, oldValue) {\n scope.disabled = scope.$eval(newValue);\n });\n\n // Push pane to parent bsTabs controller\n bsTabsCtrl.$push(scope);\n\n // remove pane from tab controller when pane is destroyed\n scope.$on('$destroy', function() {\n bsTabsCtrl.$remove(scope);\n });\n\n function render() {\n var index = bsTabsCtrl.$panes.indexOf(scope);\n $animate[bsTabsCtrl.$isActive(scope, index) ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n\n// Source: timepicker/timepicker.js\nangular.module('mgcrea.ngStrap.timepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$timepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'timepicker',\n prefixClass: 'timepicker',\n placement: 'bottom-left',\n template: 'timepicker/timepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: true,\n timeType: 'date',\n timeFormat: 'shortTime',\n timezone: null,\n modelTimeFormat: null,\n autoclose: false,\n minTime: -Infinity,\n maxTime: +Infinity,\n length: 5,\n hourStep: 1,\n minuteStep: 5,\n secondStep: 5,\n roundDisplay: false,\n iconUp: 'glyphicon glyphicon-chevron-up',\n iconDown: 'glyphicon glyphicon-chevron-down',\n arrowBehavior: 'pager'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function timepickerFactory(element, controller, config) {\n\n var $timepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $timepicker.$options;\n var scope = $timepicker.$scope;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n function floorMinutes(time)\n {\n // coeff used to floor current time to nearest minuteStep interval\n var coeff = 1000 * 60 * options.minuteStep;\n return new Date(Math.floor(time.getTime() / coeff) * coeff);\n }\n\n // View vars\n\n var selectedIndex = 0;\n var defaultDate = options.roundDisplay ? floorMinutes(new Date()) : new Date();\n var startDate = controller.$dateValue || defaultDate;\n var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n var hoursFormat = $dateFormatter.hoursFormat(format),\n timeSeparator = $dateFormatter.timeSeparator(format),\n minutesFormat = $dateFormatter.minutesFormat(format),\n secondsFormat = $dateFormatter.secondsFormat(format),\n showSeconds = $dateFormatter.showSeconds(format),\n showAM = $dateFormatter.showAM(format);\n\n scope.$iconUp = options.iconUp;\n scope.$iconDown = options.iconDown;\n\n // Scope methods\n\n scope.$select = function(date, index) {\n $timepicker.select(date, index);\n };\n scope.$moveIndex = function(value, index) {\n $timepicker.$moveIndex(value, index);\n };\n scope.$switchMeridian = function(date) {\n $timepicker.switchMeridian(date);\n };\n\n // Public methods\n\n $timepicker.update = function(date) {\n // console.warn('$timepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $timepicker.$date = date;\n angular.extend(viewDate, {hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds(), millisecond: date.getMilliseconds()});\n $timepicker.$build();\n } else if(!$timepicker.$isBuilt) {\n $timepicker.$build();\n }\n };\n\n $timepicker.select = function(date, index, keep) {\n // console.warn('$timepicker.select', date, scope.$mode);\n if(!controller.$dateValue || isNaN(controller.$dateValue.getTime())) controller.$dateValue = new Date(1970, 0, 1);\n if(!angular.isDate(date)) date = new Date(date);\n if(index === 0) controller.$dateValue.setHours(date.getHours());\n else if(index === 1) controller.$dateValue.setMinutes(date.getMinutes());\n else if(index === 2) controller.$dateValue.setSeconds(date.getSeconds());\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $timepicker.hide(true); });\n }\n };\n\n $timepicker.switchMeridian = function(date) {\n if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) {\n return;\n }\n var hours = (date || controller.$dateValue).getHours();\n controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12);\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n };\n\n // Protected methods\n\n $timepicker.$build = function() {\n // console.warn('$timepicker.$build() viewDate=%o', viewDate);\n var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n var hours = [], hour;\n for(i = 0; i < options.length; i++) {\n hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);\n hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});\n }\n var minutes = [], minute;\n for(i = 0; i < options.length; i++) {\n minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);\n minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n }\n var seconds = [], second;\n for(i = 0; i < options.length; i++) {\n second = new Date(1970, 0, 1, 0, 0, viewDate.second - (midIndex - i) * options.secondStep);\n seconds.push({date: second, label: formatDate(second, secondsFormat), selected: $timepicker.$date && $timepicker.$isSelected(second, 2), disabled: $timepicker.$isDisabled(second, 2)});\n }\n\n var rows = [];\n for(i = 0; i < options.length; i++) {\n if (showSeconds) {\n rows.push([hours[i], minutes[i], seconds[i]]);\n } else {\n rows.push([hours[i], minutes[i]]);\n }\n }\n scope.rows = rows;\n scope.showSeconds = showSeconds;\n scope.showAM = showAM;\n scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n scope.timeSeparator = timeSeparator;\n $timepicker.$isBuilt = true;\n };\n\n $timepicker.$isSelected = function(date, index) {\n if(!$timepicker.$date) return false;\n else if(index === 0) {\n return date.getHours() === $timepicker.$date.getHours();\n } else if(index === 1) {\n return date.getMinutes() === $timepicker.$date.getMinutes();\n } else if(index === 2) {\n return date.getSeconds() === $timepicker.$date.getSeconds();\n }\n };\n\n $timepicker.$isDisabled = function(date, index) {\n var selectedTime;\n if(index === 0) {\n selectedTime = date.getTime() + viewDate.minute * 6e4 + viewDate.second * 1e3;\n } else if(index === 1) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.second * 1e3;\n } else if(index === 2) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.minute * 6e4;\n }\n return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1;\n };\n\n scope.$arrowAction = function (value, index) {\n if (options.arrowBehavior === 'picker') {\n $timepicker.$setTimeByStep(value,index);\n } else {\n $timepicker.$moveIndex(value,index);\n }\n };\n\n $timepicker.$setTimeByStep = function(value, index) {\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n if (index === 0) {\n newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n }\n else if (index === 1) {\n newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\n }\n else if (index === 2) {\n newDate.setSeconds(seconds - (parseInt(options.secondStep, 10) * value));\n }\n $timepicker.select(newDate, index, true);\n };\n\n $timepicker.$moveIndex = function(value, index) {\n var targetDate;\n if(index === 0) {\n targetDate = new Date(1970, 0, 1, viewDate.hour + (value * options.length), viewDate.minute, viewDate.second);\n angular.extend(viewDate, {hour: targetDate.getHours()});\n } else if(index === 1) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + (value * options.length * options.minuteStep), viewDate.second);\n angular.extend(viewDate, {minute: targetDate.getMinutes()});\n } else if(index === 2) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute, viewDate.second + (value * options.length * options.secondStep));\n angular.extend(viewDate, {second: targetDate.getSeconds()});\n }\n $timepicker.$build();\n };\n\n $timepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n if(evt.target.nodeName.toLowerCase() !== 'input') evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $timepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Close on enter\n if(evt.keyCode === 13) return $timepicker.hide(true);\n\n // Navigate with keyboard\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n var sepLength = 1;\n var lateralMove = /(37|39)/.test(evt.keyCode);\n var count = 2 + showSeconds * 1 + showAM * 1;\n\n // Navigate indexes (left, right)\n if (lateralMove) {\n if(evt.keyCode === 37) selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1;\n else if(evt.keyCode === 39) selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0;\n }\n\n // Update values (up, down)\n var selectRange = [0, hoursLength];\n var incr = 0;\n if (evt.keyCode === 38) incr = -1;\n if (evt.keyCode === 40) incr = +1;\n var isSeconds = selectedIndex === 2 && showSeconds;\n var isMeridian = selectedIndex === 2 && !showSeconds || selectedIndex === 3 && showSeconds;\n if(selectedIndex === 0) {\n newDate.setHours(hours + incr*parseInt(options.hourStep, 10));\n // re-calculate hours length because we have changed hours value\n hoursLength = formatDate(newDate, hoursFormat).length;\n selectRange = [0, hoursLength];\n } else if(selectedIndex === 1) {\n newDate.setMinutes(minutes + incr*parseInt(options.minuteStep, 10));\n // re-calculate minutes length because we have changes minutes value\n minutesLength = formatDate(newDate, minutesFormat).length;\n selectRange = [hoursLength + sepLength, minutesLength];\n } else if(isSeconds) {\n newDate.setSeconds(seconds + incr*parseInt(options.secondStep, 10));\n // re-calculate seconds length because we have changes seconds value\n secondsLength = formatDate(newDate, secondsFormat).length;\n selectRange = [hoursLength + sepLength + minutesLength + sepLength, secondsLength];\n } else if(isMeridian) {\n if(!lateralMove) $timepicker.switchMeridian();\n selectRange = [hoursLength + sepLength + minutesLength + sepLength + (secondsLength + sepLength)*showSeconds, 2];\n }\n $timepicker.select(newDate, selectedIndex, true);\n createSelection(selectRange[0], selectRange[1]);\n parentScope.$digest();\n };\n\n // Private\n\n function createSelection(start, length) {\n var end = start + length;\n if(element[0].createTextRange) {\n var selRange = element[0].createTextRange();\n selRange.collapse(true);\n selRange.moveStart('character', start);\n selRange.moveEnd('character', end);\n selRange.select();\n } else if(element[0].setSelectionRange) {\n element[0].setSelectionRange(start, end);\n } else if(angular.isUndefined(element[0].selectionStart)) {\n element[0].selectionStart = start;\n element[0].selectionEnd = end;\n }\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $timepicker.init;\n $timepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'time');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $timepicker.destroy;\n $timepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $timepicker.show;\n $timepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $timepicker.$element && $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element && element.on('keydown', $timepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $timepicker.hide;\n $timepicker.hide = function(blur) {\n if(!$timepicker.$isShown) return;\n $timepicker.$element && $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element && element.off('keydown', $timepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $timepicker;\n\n }\n\n timepickerFactory.defaults = defaults;\n return timepickerFactory;\n\n };\n\n })\n\n\n .directive('bsTimepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n var defaults = $timepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'timeType', 'timeFormat', 'timezone', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'secondStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'roundDisplay', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative', 'roundDisplay'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!timepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(timepicker),?/i);\n newValue === true ? timepicker.show() : timepicker.hide();\n });\n\n // Initialize timepicker\n if(isNative && (options.useNative || defaults.useNative)) options.timeFormat = 'HH:mm';\n var timepicker = $timepicker(element, controller, options);\n options = timepicker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n // Initialize parser\n var dateParser = $dateParser({format: options.timeFormat, lang: lang});\n\n // Observe attributes for changes\n angular.forEach(['minTime', 'maxTime'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n !isNaN(timepicker.$options[key]) && timepicker.$build();\n validateAgainstMinMaxTime(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue);\n timepicker.update(controller.$dateValue);\n }, true);\n\n function validateAgainstMinMaxTime(parsedTime) {\n if (!angular.isDate(parsedTime)) return;\n var isMinValid = isNaN(options.minTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) >= options.minTime;\n var isMaxValid = isNaN(options.maxTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) <= options.maxTime;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(!isValid) {\n return;\n }\n controller.$dateValue = parsedTime;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n controller.$setValidity('date', true);\n return null;\n }\n var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedTime || isNaN(parsedTime.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxTime(parsedTime);\n }\n\n if(options.timeType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedTime, options.timezone, true);\n return formatDate(date, options.modelTimeFormat || options.timeFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.timeType === 'number') {\n return date.getTime();\n } else if(options.timeType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.timeType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.timeType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelTimeFormat);\n } else if(options.timeType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5);\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getTimeFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getTimeFormattedString());\n };\n\n function getTimeFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (timepicker) timepicker.destroy();\n options = null;\n timepicker = null;\n });\n\n }\n };\n\n });\n\n// Source: tooltip/tooltip.js\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$tooltip', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n prefixClass: 'tooltip',\n prefixEvent: 'tooltip',\n container: false,\n target: false,\n placement: 'top',\n template: 'tooltip/tooltip.tpl.html',\n contentTemplate: false,\n trigger: 'hover focus',\n keyboard: false,\n html: false,\n show: false,\n title: '',\n type: '',\n delay: 0,\n autoClose: false,\n bsEnabled: true,\n viewport: {\n selector: 'body',\n padding: 0\n }\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n var trim = String.prototype.trim;\n var isTouch = 'createTouch' in $window.document;\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n var $body = angular.element($window.document);\n\n function TooltipFactory(element, config) {\n\n var $tooltip = {};\n\n // Common vars\n var nodeName = element[0].nodeName.toLowerCase();\n var options = $tooltip.$options = angular.extend({}, defaults, config);\n $tooltip.$promise = fetchTemplate(options.template);\n var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(options.delay && angular.isString(options.delay)) {\n var split = options.delay.split(',').map(parseFloat);\n options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $tooltip.$id = options.id || element.attr('id') || '';\n\n // Support scope as string options\n if(options.title) {\n scope.title = $sce.trustAsHtml(options.title);\n }\n\n // Provide scope helpers\n scope.$setEnabled = function(isEnabled) {\n scope.$$postDigest(function() {\n $tooltip.setEnabled(isEnabled);\n });\n };\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $tooltip.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $tooltip.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $tooltip.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $tooltip.$isShown = scope.$isShown = false;\n\n // Private vars\n var timeout, hoverState;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $tooltip.$promise = $tooltip.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]);\n if(!contentEl.length) contentEl = findElement('[ng-bind=\"title\"]', templateEl[0]);\n contentEl.removeAttr('ng-bind').html(contentTemplate);\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize tooltip\n var tipLinker, tipElement, tipTemplate, tipContainer, tipScope;\n $tooltip.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n tipTemplate = template;\n tipLinker = $compile(template);\n $tooltip.init();\n });\n\n $tooltip.init = function() {\n\n // Options: delay\n if (options.delay && angular.isNumber(options.delay)) {\n options.delay = {\n show: options.delay,\n hide: options.delay\n };\n }\n\n // Replace trigger on touch devices ?\n // if(isTouch && options.trigger === defaults.trigger) {\n // options.trigger.replace(/hover/g, 'click');\n // }\n\n // Options : container\n if(options.container === 'self') {\n tipContainer = element;\n } else if(angular.isElement(options.container)) {\n tipContainer = options.container;\n } else if(options.container) {\n tipContainer = findElement(options.container);\n }\n\n // Options: trigger\n bindTriggerEvents();\n\n // Options: target\n if(options.target) {\n options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n }\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n options.trigger === 'focus' ? element[0].focus() : $tooltip.show();\n });\n }\n\n };\n\n $tooltip.destroy = function() {\n\n // Unbind events\n unbindTriggerEvents();\n\n // Remove element\n destroyTipElement();\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $tooltip.enter = function() {\n\n clearTimeout(timeout);\n hoverState = 'in';\n if (!options.delay || !options.delay.show) {\n return $tooltip.show();\n }\n\n timeout = setTimeout(function() {\n if (hoverState ==='in') $tooltip.show();\n }, options.delay.show);\n\n };\n\n $tooltip.show = function() {\n if (!options.bsEnabled || $tooltip.$isShown) return;\n\n scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n var parent, after;\n if (options.container) {\n parent = tipContainer;\n if (tipContainer[0].lastChild) {\n after = angular.element(tipContainer[0].lastChild);\n } else {\n after = null;\n }\n } else {\n parent = null;\n after = element;\n }\n\n\n // Hide any existing tipElement\n if(tipElement) destroyTipElement();\n // Fetch a cloned element linked from template\n tipScope = $tooltip.$scope.$new();\n tipElement = $tooltip.$element = tipLinker(tipScope, function(clonedElement, scope) {});\n\n // Set the initial positioning. Make the tooltip invisible\n // so IE doesn't try to focus on it off screen.\n tipElement.css({top: '-9999px', left: '-9999px', right: 'auto', display: 'block', visibility: 'hidden'});\n\n // Options: animation\n if(options.animation) tipElement.addClass(options.animation);\n // Options: type\n if(options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n // Options: custom classes\n if(options.customClass) tipElement.addClass(options.customClass);\n\n // Append the element, without any animations. If we append\n // using $animate.enter, some of the animations cause the placement\n // to be off due to the transforms.\n after ? after.after(tipElement) : parent.prepend(tipElement);\n\n $tooltip.$isShown = scope.$isShown = true;\n safeDigest(scope);\n\n // Now, apply placement\n $tooltip.$applyPlacement();\n\n // Once placed, animate it.\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if(angular.version.minor <= 2) {\n $animate.enter(tipElement, parent, after, enterAnimateCallback);\n } else {\n $animate.enter(tipElement, parent, after).then(enterAnimateCallback);\n }\n safeDigest(scope);\n\n $$rAF(function () {\n // Once the tooltip is placed and the animation starts, make the tooltip visible\n if(tipElement) tipElement.css({visibility: 'visible'});\n });\n\n // Bind events\n if(options.keyboard) {\n if(options.trigger !== 'focus') {\n $tooltip.focus();\n }\n bindKeyboardEvents();\n }\n\n if(options.autoClose) {\n bindAutoCloseEvents();\n }\n\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $tooltip);\n }\n\n $tooltip.leave = function() {\n\n clearTimeout(timeout);\n hoverState = 'out';\n if (!options.delay || !options.delay.hide) {\n return $tooltip.hide();\n }\n timeout = setTimeout(function () {\n if (hoverState === 'out') {\n $tooltip.hide();\n }\n }, options.delay.hide);\n\n };\n\n var _blur;\n var _tipToHide;\n $tooltip.hide = function(blur) {\n\n if(!$tooltip.$isShown) return;\n scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n\n // store blur value for leaveAnimateCallback to use\n _blur = blur;\n\n // store current tipElement reference to use\n // in leaveAnimateCallback\n _tipToHide = tipElement;\n\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if(angular.version.minor <= 2) {\n $animate.leave(tipElement, leaveAnimateCallback);\n } else {\n $animate.leave(tipElement).then(leaveAnimateCallback);\n }\n\n $tooltip.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.keyboard && tipElement !== null) {\n unbindKeyboardEvents();\n }\n\n if(options.autoClose && tipElement !== null) {\n unbindAutoCloseEvents();\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\n\n // check if current tipElement still references\n // the same element when hide was called\n if (tipElement === _tipToHide) {\n // Allow to blur the input when hidden, like when pressing enter key\n if(_blur && options.trigger === 'focus') {\n return element[0].blur();\n }\n\n // clean up child scopes\n destroyTipElement();\n }\n }\n\n $tooltip.toggle = function() {\n $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter();\n };\n\n $tooltip.focus = function() {\n tipElement[0].focus();\n };\n\n $tooltip.setEnabled = function(isEnabled) {\n options.bsEnabled = isEnabled;\n };\n\n $tooltip.setViewport = function(viewport) {\n options.viewport = viewport;\n };\n\n // Protected methods\n\n $tooltip.$applyPlacement = function() {\n if(!tipElement) return;\n\n // Determine if we're doing an auto or normal placement\n var placement = options.placement,\n autoToken = /\\s?auto?\\s?/i,\n autoPlace = autoToken.test(placement);\n\n if (autoPlace) {\n placement = placement.replace(autoToken, '') || defaults.placement;\n }\n\n // Need to add the position class before we get\n // the offsets\n tipElement.addClass(options.placement);\n\n // Get the position of the target element\n // and the height and width of the tooltip so we can center it.\n var elementPosition = getPosition(),\n tipWidth = tipElement.prop('offsetWidth'),\n tipHeight = tipElement.prop('offsetHeight');\n\n // If we're auto placing, we need to check the positioning\n if (autoPlace) {\n var originalPlacement = placement;\n var container = options.container ? findElement(options.container) : element.parent();\n var containerPosition = getPosition(container);\n\n // Determine if the vertical placement\n if (originalPlacement.indexOf('bottom') >= 0 && elementPosition.bottom + tipHeight > containerPosition.bottom) {\n placement = originalPlacement.replace('bottom', 'top');\n } else if (originalPlacement.indexOf('top') >= 0 && elementPosition.top - tipHeight < containerPosition.top) {\n placement = originalPlacement.replace('top', 'bottom');\n }\n\n // Determine the horizontal placement\n // The exotic placements of left and right are opposite of the standard placements. Their arrows are put on the left/right\n // and flow in the opposite direction of their placement.\n if ((originalPlacement === 'right' || originalPlacement === 'bottom-left' || originalPlacement === 'top-left') &&\n elementPosition.right + tipWidth > containerPosition.width) {\n\n placement = originalPlacement === 'right' ? 'left' : placement.replace('left', 'right');\n } else if ((originalPlacement === 'left' || originalPlacement === 'bottom-right' || originalPlacement === 'top-right') &&\n elementPosition.left - tipWidth < containerPosition.left) {\n\n placement = originalPlacement === 'left' ? 'right' : placement.replace('right', 'left');\n }\n\n tipElement.removeClass(originalPlacement).addClass(placement);\n }\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n applyPlacement(tipPosition, placement);\n };\n\n $tooltip.$onKeyUp = function(evt) {\n if (evt.which === 27 && $tooltip.$isShown) {\n $tooltip.hide();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusKeyUp = function(evt) {\n if (evt.which === 27) {\n element[0].blur();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusElementMouseDown = function(evt) {\n evt.preventDefault();\n evt.stopPropagation();\n // Some browsers do not auto-focus buttons (eg. Safari)\n $tooltip.$isShown ? element[0].blur() : element[0].focus();\n };\n\n // bind/unbind events\n function bindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n angular.forEach(triggers, function(trigger) {\n if(trigger === 'click') {\n element.on('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n });\n }\n\n function unbindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n for (var i = triggers.length; i--;) {\n var trigger = triggers[i];\n if(trigger === 'click') {\n element.off('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n }\n }\n\n function bindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.on('keyup', $tooltip.$onKeyUp);\n } else {\n element.on('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n function unbindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.off('keyup', $tooltip.$onKeyUp);\n } else {\n element.off('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n var _autoCloseEventsBinded = false;\n function bindAutoCloseEvents() {\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // Stop propagation when clicking inside tooltip\n tipElement.on('click', stopEventPropagation);\n\n // Hide when clicking outside tooltip\n $body.on('click', $tooltip.hide);\n\n _autoCloseEventsBinded = true;\n }, 0, false);\n }\n\n function unbindAutoCloseEvents() {\n if (_autoCloseEventsBinded) {\n tipElement.off('click', stopEventPropagation);\n $body.off('click', $tooltip.hide);\n _autoCloseEventsBinded = false;\n }\n }\n\n function stopEventPropagation(event) {\n event.stopPropagation();\n }\n\n // Private methods\n\n function getPosition($element) {\n $element = $element || (options.target || element);\n\n var el = $element[0],\n isBody = el.tagName === 'BODY';\n\n var elRect = el.getBoundingClientRect();\n var rect = {};\n\n // IE8 has issues with angular.extend and using elRect directly.\n // By coping the values of elRect into a new object, we can continue to use extend\n for (var p in elRect) {\n // DO NOT use hasOwnProperty when inspecting the return of getBoundingClientRect.\n rect[p] = elRect[p];\n }\n\n if (rect.width === null) {\n // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n rect = angular.extend({}, rect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });\n }\n var elOffset = isBody ? { top: 0, left: 0 } : dimensions.offset(el),\n scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.prop('scrollTop') || 0 },\n outerDims = isBody ? { width: document.documentElement.clientWidth, height: $window.innerHeight } : null;\n\n return angular.extend({}, rect, scroll, outerDims, elOffset);\n }\n\n function getCalculatedOffset(placement, position, actualWidth, actualHeight) {\n var offset;\n var split = placement.split('-');\n\n switch (split[0]) {\n case 'right':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left + position.width\n };\n break;\n case 'bottom':\n offset = {\n top: position.top + position.height,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n case 'left':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left - actualWidth\n };\n break;\n default:\n offset = {\n top: position.top - actualHeight,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n }\n\n if(!split[1]) {\n return offset;\n }\n\n // Add support for corners @todo css\n if(split[0] === 'top' || split[0] === 'bottom') {\n switch (split[1]) {\n case 'left':\n offset.left = position.left;\n break;\n case 'right':\n offset.left = position.left + position.width - actualWidth;\n }\n } else if(split[0] === 'left' || split[0] === 'right') {\n switch (split[1]) {\n case 'top':\n offset.top = position.top - actualHeight;\n break;\n case 'bottom':\n offset.top = position.top + position.height;\n }\n }\n\n return offset;\n }\n\n function applyPlacement(offset, placement) {\n var tip = tipElement[0],\n width = tip.offsetWidth,\n height = tip.offsetHeight;\n\n // manually read margins because getBoundingClientRect includes difference\n var marginTop = parseInt(dimensions.css(tip, 'margin-top'), 10),\n marginLeft = parseInt(dimensions.css(tip, 'margin-left'), 10);\n\n // we must check for NaN for ie 8/9\n if (isNaN(marginTop)) marginTop = 0;\n if (isNaN(marginLeft)) marginLeft = 0;\n\n offset.top = offset.top + marginTop;\n offset.left = offset.left + marginLeft;\n\n // dimensions setOffset doesn't round pixel values\n // so we use setOffset directly with our own function\n dimensions.setOffset(tip, angular.extend({\n using: function (props) {\n tipElement.css({\n top: Math.round(props.top) + 'px',\n left: Math.round(props.left) + 'px',\n right: ''\n });\n }\n }, offset), 0);\n\n // check to see if placing tip in new offset caused the tip to resize itself\n var actualWidth = tip.offsetWidth,\n actualHeight = tip.offsetHeight;\n\n if (placement === 'top' && actualHeight !== height) {\n offset.top = offset.top + height - actualHeight;\n }\n\n // If it's an exotic placement, exit now instead of\n // applying a delta and changing the arrow\n if (/top-left|top-right|bottom-left|bottom-right/.test(placement)) return;\n\n var delta = getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);\n\n if (delta.left) {\n offset.left += delta.left;\n } else {\n offset.top += delta.top;\n }\n\n dimensions.setOffset(tip, offset);\n\n if (/top|right|bottom|left/.test(placement)) {\n var isVertical = /top|bottom/.test(placement),\n arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight,\n arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';\n\n replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical);\n }\n }\n\n function getViewportAdjustedDelta(placement, position, actualWidth, actualHeight) {\n var delta = { top: 0, left: 0 },\n $viewport = options.viewport && findElement(options.viewport.selector || options.viewport);\n\n if (!$viewport) {\n return delta;\n }\n\n var viewportPadding = options.viewport && options.viewport.padding || 0,\n viewportDimensions = getPosition($viewport);\n\n if (/right|left/.test(placement)) {\n var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll,\n bottomEdgeOffset = position.top + viewportPadding - viewportDimensions.scroll + actualHeight;\n if (topEdgeOffset < viewportDimensions.top) { // top overflow\n delta.top = viewportDimensions.top - topEdgeOffset;\n } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;\n }\n } else {\n var leftEdgeOffset = position.left - viewportPadding,\n rightEdgeOffset = position.left + viewportPadding + actualWidth;\n if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n delta.left = viewportDimensions.left - leftEdgeOffset;\n } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow\n delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;\n }\n }\n\n return delta;\n }\n\n function replaceArrow(delta, dimension, isHorizontal) {\n var $arrow = findElement('.tooltip-arrow, .arrow', tipElement[0]);\n\n $arrow.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')\n .css(isHorizontal ? 'top' : 'left', '');\n }\n\n function destroyTipElement() {\n // Cancel pending callbacks\n clearTimeout(timeout);\n\n if($tooltip.$isShown && tipElement !== null) {\n if(options.autoClose) {\n unbindAutoCloseEvents();\n }\n\n if(options.keyboard) {\n unbindKeyboardEvents();\n }\n }\n\n if(tipScope) {\n tipScope.$destroy();\n tipScope = null;\n }\n\n if(tipElement) {\n tipElement.remove();\n tipElement = $tooltip.$element = null;\n }\n }\n\n return $tooltip;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return TooltipFactory;\n\n };\n\n })\n\n .directive('bsTooltip', function($window, $location, $sce, $tooltip, $$rAF) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Observe scope attributes for change\n attr.$observe('title', function(newValue) {\n if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n var oldValue = scope.title;\n scope.title = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }\n });\n\n // Support scope as an object\n attr.bsTooltip && scope.$watch(attr.bsTooltip, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.title = newValue;\n }\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n newValue === true ? tooltip.show() : tooltip.hide();\n });\n\n // Enabled binding support\n attr.bsEnabled && scope.$watch(attr.bsEnabled, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n newValue === false ? tooltip.setEnabled(false) : tooltip.setEnabled(true);\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n tooltip.setViewport(newValue);\n });\n\n // Initialize popover\n var tooltip = $tooltip(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(tooltip) tooltip.destroy();\n options = null;\n tooltip = null;\n });\n\n }\n };\n\n });\n\n// Source: typeahead/typeahead.js\nangular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$typeahead', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'typeahead',\n prefixEvent: '$typeahead',\n placement: 'bottom-left',\n template: 'typeahead/typeahead.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n minLength: 1,\n filter: 'filter',\n limit: 6,\n autoSelect: false,\n comparator: '',\n trimValue: true\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n\n function TypeaheadFactory(element, controller, config) {\n\n var $typeahead = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $typeahead = $tooltip(element, options);\n var parentScope = config.scope;\n var scope = $typeahead.$scope;\n\n scope.$resetMatches = function(){\n scope.$matches = [];\n scope.$activeIndex = options.autoSelect ? 0 : -1; // If set to 0, the first match will be highlighted\n };\n scope.$resetMatches();\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $typeahead.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $typeahead.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $typeahead.$isVisible();\n };\n\n // Public methods\n\n $typeahead.update = function(matches) {\n scope.$matches = matches;\n if(scope.$activeIndex >= matches.length) {\n scope.$activeIndex = options.autoSelect ? 0: -1;\n }\n\n // When the placement is not one of the bottom placements, re-calc the positioning\n // so the results render correctly.\n if (/^(bottom|bottom-left|bottom-right)$/.test(options.placement)) return;\n\n // wrap in a $timeout so the results are updated\n // before repositioning\n $timeout($typeahead.$applyPlacement);\n };\n\n $typeahead.activate = function(index) {\n scope.$activeIndex = index;\n };\n\n $typeahead.select = function(index) {\n if(index === -1) return;\n var value = scope.$matches[index].value;\n // console.log('$setViewValue', value);\n controller.$setViewValue(value);\n controller.$render();\n scope.$resetMatches();\n if(parentScope) parentScope.$digest();\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $typeahead);\n };\n\n // Protected methods\n\n $typeahead.$isVisible = function() {\n if(!options.minLength || !controller) {\n return !!scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength;\n };\n\n $typeahead.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $typeahead.$onMouseDown = function(evt) {\n // Prevent blur on mousedown\n evt.preventDefault();\n evt.stopPropagation();\n };\n\n $typeahead.$onKeyDown = function(evt) {\n if(!/(38|40|13)/.test(evt.keyCode)) return;\n\n // Let ngSubmit pass if the typeahead tip is hidden or no option is selected\n if($typeahead.$isVisible() && !(evt.keyCode === 13 && scope.$activeIndex === -1)) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n // Select with enter\n if(evt.keyCode === 13 && scope.$matches.length) {\n $typeahead.select(scope.$activeIndex);\n }\n\n // Navigate with keyboard\n else if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n };\n\n // Overrides\n\n var show = $typeahead.show;\n $typeahead.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed immediately.\n $timeout(function() {\n $typeahead.$element && $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element && element.on('keydown', $typeahead.$onKeyDown);\n }\n }, 0, false);\n };\n\n var hide = $typeahead.hide;\n $typeahead.hide = function() {\n $typeahead.$element && $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element && element.off('keydown', $typeahead.$onKeyDown);\n }\n if(!options.autoSelect)\n $typeahead.activate(-1);\n hide();\n };\n\n return $typeahead;\n\n }\n\n TypeaheadFactory.defaults = defaults;\n return TypeaheadFactory;\n\n };\n\n })\n\n .directive('bsTypeahead', function($window, $parse, $q, $typeahead, $parseOptions) {\n\n var defaults = $typeahead.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'filter', 'limit', 'minLength', 'watchOptions', 'selectMode', 'autoSelect', 'comparator', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'trimValue'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n });\n\n // Disable browser autocompletion\n element.attr('autocomplete' ,'off');\n\n // Build proper bsOptions\n var filter = options.filter || defaults.filter;\n var limit = options.limit || defaults.limit;\n var comparator = options.comparator || defaults.comparator;\n\n var bsOptions = attr.bsOptions;\n if(filter) bsOptions += ' | ' + filter + ':$viewValue';\n if (comparator) bsOptions += ':' + comparator;\n if(limit) bsOptions += ' | limitTo:' + limit;\n var parsedOptions = $parseOptions(bsOptions);\n\n // Initialize typeahead\n var typeahead = $typeahead(element, controller, options);\n\n // Watch options on demand\n if(options.watchOptions) {\n // Watch bsOptions values before filtering for changes, drop function calls\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n scope.$watchCollection(watchedOptions, function (newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller).then(function (values) {\n typeahead.update(values);\n controller.$render();\n });\n });\n }\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('$watch', element.attr('ng-model'), newValue);\n scope.$modelValue = newValue; // Publish modelValue on scope for custom templates\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n // Prevent input with no future prospect if selectMode is truthy\n // @TODO test selectMode\n if(options.selectMode && !values.length && newValue.length > 0) {\n controller.$setViewValue(controller.$viewValue.substring(0, controller.$viewValue.length - 1));\n return;\n }\n if(values.length > limit) values = values.slice(0, limit);\n var isVisible = typeahead.$isVisible();\n isVisible && typeahead.update(values);\n // Do not re-queue an update if a correct value has been selected\n if(values.length === 1 && values[0].value === newValue) return;\n !isVisible && typeahead.update(values);\n // Queue a new rendering that will leverage collection loading\n controller.$render();\n });\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var displayValue = parsedOptions.displayValue(modelValue);\n\n // If we can determine the displayValue, use that\n if (displayValue) return displayValue;\n\n // If there's no display value, attempt to use the modelValue.\n // If the model is an object not much we can do\n if (modelValue && typeof modelValue !== 'object') {\n return modelValue;\n }\n return '';\n });\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n if(controller.$isEmpty(controller.$viewValue)) return element.val('');\n var index = typeahead.$getIndex(controller.$modelValue);\n var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;\n selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;\n var value = selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '') : '';\n element.val(options.trimValue === false ? value : value.trim());\n };\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (typeahead) typeahead.destroy();\n options = null;\n typeahead = null;\n });\n\n }\n };\n\n });\n\n})(window, document);\n","'use strict';\n\nangular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mgcrea.ngStrap.helpers.debounce'])\n\n .provider('$affix', function() {\n\n var defaults = this.defaults = {\n offsetTop: 'auto',\n inlineStyles: true\n };\n\n this.$get = function($window, debounce, dimensions) {\n\n var bodyEl = angular.element($window.document.body);\n var windowEl = angular.element($window);\n\n function AffixFactory(element, config) {\n\n var $affix = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var targetEl = options.target;\n\n // Initial private vars\n var reset = 'affix affix-top affix-bottom',\n setWidth = false,\n initialAffixTop = 0,\n initialOffsetTop = 0,\n offsetTop = 0,\n offsetBottom = 0,\n affixed = null,\n unpin = null;\n\n var parent = element.parent();\n // Options: custom parent\n if (options.offsetParent) {\n if (options.offsetParent.match(/^\\d+$/)) {\n for (var i = 0; i < (options.offsetParent * 1) - 1; i++) {\n parent = parent.parent();\n }\n }\n else {\n parent = angular.element(options.offsetParent);\n }\n }\n\n $affix.init = function() {\n\n this.$parseOffsets();\n initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n setWidth = !element[0].style.width;\n\n // Bind events\n targetEl.on('scroll', this.checkPosition);\n targetEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', this.$debouncedOnResize);\n\n // Both of these checkPosition() calls are necessary for the case where\n // the user hits refresh after scrolling to the bottom of the page.\n this.checkPosition();\n this.checkPositionWithEventLoop();\n\n };\n\n $affix.destroy = function() {\n\n // Unbind events\n targetEl.off('scroll', this.checkPosition);\n targetEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', this.$debouncedOnResize);\n\n };\n\n $affix.checkPositionWithEventLoop = function() {\n\n // IE 9 throws an error if we use 'this' instead of '$affix'\n // in this setTimeout call\n setTimeout($affix.checkPosition, 1);\n\n };\n\n $affix.checkPosition = function() {\n // if (!this.$element.is(':visible')) return\n\n var scrollTop = getScrollTop();\n var position = dimensions.offset(element[0]);\n var elementHeight = dimensions.height(element[0]);\n\n // Get required affix class according to position\n var affix = getRequiredAffixClass(unpin, position, elementHeight);\n\n // Did affix status changed this last check?\n if(affixed === affix) return;\n affixed = affix;\n\n // Add proper affix class\n element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\n\n if(affix === 'top') {\n unpin = null;\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', '');\n }\n } else if(affix === 'bottom') {\n if (options.offsetUnpin) {\n unpin = -(options.offsetUnpin * 1);\n }\n else {\n // Calculate unpin threshold when affixed to bottom.\n // Hopefully the browser scrolls pixel by pixel.\n unpin = position.top - scrollTop;\n }\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n }\n } else { // affix === 'middle'\n unpin = null;\n if(setWidth) {\n element.css('width', element[0].offsetWidth + 'px');\n }\n if (options.inlineStyles) {\n element.css('position', 'fixed');\n element.css('top', initialAffixTop + 'px');\n }\n }\n\n };\n\n $affix.$onResize = function() {\n $affix.$parseOffsets();\n $affix.checkPosition();\n };\n $affix.$debouncedOnResize = debounce($affix.$onResize, 50);\n\n $affix.$parseOffsets = function() {\n var initialPosition = element.css('position');\n // Reset position to calculate correct offsetTop\n if (options.inlineStyles){\n element.css('position', (options.offsetParent) ? '' : 'relative');\n }\n\n if(options.offsetTop) {\n if(options.offsetTop === 'auto') {\n options.offsetTop = '+0';\n }\n if(options.offsetTop.match(/^[-+]\\d+$/)) {\n initialAffixTop = - options.offsetTop * 1;\n if(options.offsetParent) {\n offsetTop = dimensions.offset(parent[0]).top + (options.offsetTop * 1);\n }\n else {\n offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\n }\n }\n else {\n offsetTop = options.offsetTop * 1;\n }\n }\n\n if(options.offsetBottom) {\n if(options.offsetParent && options.offsetBottom.match(/^[-+]\\d+$/)) {\n // add 1 pixel due to rounding problems...\n offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + (options.offsetBottom * 1) + 1;\n }\n else {\n offsetBottom = options.offsetBottom * 1;\n }\n }\n\n // Bring back the element's position after calculations\n if (options.inlineStyles){\n element.css('position', initialPosition);\n }\n };\n\n // Private methods\n\n function getRequiredAffixClass(unpin, position, elementHeight) {\n\n var scrollTop = getScrollTop();\n var scrollHeight = getScrollHeight();\n\n if(scrollTop <= offsetTop) {\n return 'top';\n } else if(unpin !== null && (scrollTop + unpin <= position.top)) {\n return 'middle';\n } else if(offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n return 'bottom';\n } else {\n return 'middle';\n }\n\n }\n\n function getScrollTop() {\n return targetEl[0] === $window ? $window.pageYOffset : targetEl[0].scrollTop;\n }\n\n function getScrollHeight() {\n return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight;\n }\n\n $affix.init();\n return $affix;\n\n }\n\n return AffixFactory;\n\n };\n\n })\n\n .directive('bsAffix', function($affix, $window) {\n\n return {\n restrict: 'EAC',\n require: '^?bsAffixTarget',\n link: function postLink(scope, element, attr, affixTarget) {\n\n var options = {scope: scope, target: affixTarget ? affixTarget.$element : angular.element($window)};\n angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin', 'inlineStyles'], function(key) {\n if(angular.isDefined(attr[key])) {\n var option = attr[key];\n if (/true/i.test(option)) option = true;\n if (/false/i.test(option)) option = false;\n options[key] = option;\n }\n });\n\n var affix = $affix(element, options);\n scope.$on('$destroy', function() {\n affix && affix.destroy();\n options = null;\n affix = null;\n });\n\n }\n };\n\n })\n\n .directive('bsAffixTarget', function() {\n return {\n controller: function($element) {\n this.$element = $element;\n }\n };\n });\n","'use strict';\n\n// @BUG: following snippet won't compile correctly\n// @TODO: submit issue to core\n// '<span ng-if=\"title\"><strong ng-bind=\"title\"></strong>&nbsp;</span><span ng-bind-html=\"content\"></span>' +\n\nangular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal'])\n\n .provider('$alert', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'alert',\n prefixEvent: 'alert',\n placement: null,\n template: 'alert/alert.tpl.html',\n container: false,\n element: null,\n backdrop: false,\n keyboard: true,\n show: true,\n // Specific options\n duration: false,\n type: false,\n dismissable: true\n };\n\n this.$get = function($modal, $timeout) {\n\n function AlertFactory(config) {\n\n var $alert = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $alert = $modal(options);\n\n // Support scope as string options [/*title, content, */ type, dismissable]\n $alert.$scope.dismissable = !!options.dismissable;\n if(options.type) {\n $alert.$scope.type = options.type;\n }\n\n // Support auto-close duration\n var show = $alert.show;\n if(options.duration) {\n $alert.show = function() {\n show();\n $timeout(function() {\n $alert.hide();\n }, options.duration * 1000);\n };\n }\n\n return $alert;\n\n }\n\n return AlertFactory;\n\n };\n\n })\n\n .directive('bsAlert', function($window, $sce, $alert) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'placement', 'keyboard', 'html', 'container', 'animation', 'duration', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['keyboard', 'html', 'container', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content', 'type'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAlert && scope.$watch(attr.bsAlert, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize alert\n var alert = $alert(options);\n\n // Trigger\n element.on(attr.trigger || 'click', alert.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (alert) alert.destroy();\n options = null;\n alert = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal'])\n\n .provider('$aside', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade-and-slide-right',\n prefixClass: 'aside',\n prefixEvent: 'aside',\n placement: 'right',\n template: 'aside/aside.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($modal) {\n\n function AsideFactory(config) {\n\n var $aside = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $aside = $modal(options);\n\n return $aside;\n\n }\n\n return AsideFactory;\n\n };\n\n })\n\n .directive('bsAside', function($window, $sce, $aside) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAside && scope.$watch(attr.bsAside, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize aside\n var aside = $aside(options);\n\n // Trigger\n element.on(attr.trigger || 'click', aside.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (aside) aside.destroy();\n options = null;\n aside = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.collapse', [])\n\n .provider('$collapse', function() {\n\n var defaults = this.defaults = {\n animation: 'am-collapse',\n disallowToggle: false,\n activeClass: 'in',\n startCollapsed: false,\n allowMultiple: false\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['disallowToggle', 'startCollapsed', 'allowMultiple'], function(key) {\n if(angular.isDefined($attrs[key]) && falseValueRegExp.test($attrs[key]))\n self.$options[key] = false;\n });\n\n self.$toggles = [];\n self.$targets = [];\n\n self.$viewChangeListeners = [];\n\n self.$registerToggle = function(element) {\n self.$toggles.push(element);\n };\n self.$registerTarget = function(element) {\n self.$targets.push(element);\n };\n\n self.$unregisterToggle = function(element) {\n var index = self.$toggles.indexOf(element);\n // remove toggle from $toggles array\n self.$toggles.splice(index, 1);\n };\n self.$unregisterTarget = function(element) {\n var index = self.$targets.indexOf(element);\n\n // remove element from $targets array\n self.$targets.splice(index, 1);\n\n if (self.$options.allowMultiple) {\n // remove target index from $active array values\n deactivateItem(element);\n }\n\n // fix active item indexes\n fixActiveItemIndexes(index);\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n // use array to store all the currently open panels\n self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n self.$setActive = $scope.$setActive = function(value) {\n if(angular.isArray(value)) {\n self.$targets.$active = value;\n }\n else if(!self.$options.disallowToggle) {\n // toogle element active status\n isActive(value) ? deactivateItem(value) : activateItem(value);\n } else {\n activateItem(value);\n }\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$activeIndexes = function() {\n return self.$options.allowMultiple ? self.$targets.$active :\n self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n };\n\n function fixActiveItemIndexes(index) {\n // item with index was removed, so we\n // need to adjust other items index values\n var activeIndexes = self.$targets.$active;\n for(var i = 0; i < activeIndexes.length; i++) {\n if (index < activeIndexes[i]) {\n activeIndexes[i] = activeIndexes[i] - 1;\n }\n\n // the last item is active, so we need to\n // adjust its index\n if (activeIndexes[i] === self.$targets.length) {\n activeIndexes[i] = self.$targets.length - 1;\n }\n }\n }\n\n function isActive(value) {\n var activeItems = self.$targets.$active;\n return activeItems.indexOf(value) === -1 ? false : true;\n }\n\n function deactivateItem(value) {\n var index = self.$targets.$active.indexOf(value);\n if (index !== -1) {\n self.$targets.$active.splice(index, 1);\n }\n }\n\n function activateItem(value) {\n if (!self.$options.allowMultiple) {\n // remove current selected item\n self.$targets.$active.splice(0, 1);\n }\n\n if (self.$targets.$active.indexOf(value) === -1) {\n self.$targets.$active.push(value);\n }\n }\n\n };\n\n this.$get = function() {\n var $collapse = {};\n $collapse.defaults = defaults;\n $collapse.controller = controller;\n return $collapse;\n };\n\n })\n\n .directive('bsCollapse', function($window, $animate, $collapse) {\n\n var defaults = $collapse.defaults;\n\n return {\n require: ['?ngModel', 'bsCollapse'],\n controller: ['$scope', '$element', '$attrs', $collapse.controller],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n if (angular.isArray(modelValue)) {\n // model value is an array, so just replace\n // the active items directly\n bsCollapseCtrl.$setActive(modelValue);\n }\n else {\n var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n if (angular.isArray(activeIndexes)) {\n // we have an array of selected indexes\n if (activeIndexes.indexOf(modelValue * 1) === -1) {\n // item with modelValue index is not active\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n else if (activeIndexes !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n return modelValue;\n });\n\n }\n\n }\n };\n\n })\n\n .directive('bsCollapseToggle', function() {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base attr\n element.attr('data-toggle', 'collapse');\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerToggle(element);\n\n // remove toggle from collapse controller when toggle is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterToggle(element);\n });\n\n element.on('click', function() {\n var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n bsCollapseCtrl.$setActive(index * 1);\n scope.$apply();\n });\n\n }\n };\n\n })\n\n .directive('bsCollapseTarget', function($animate) {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n // scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base class\n element.addClass('collapse');\n\n // Add animation class\n if(bsCollapseCtrl.$options.animation) {\n element.addClass(bsCollapseCtrl.$options.animation);\n }\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerTarget(element);\n\n // remove pane target from collapse controller when target is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterTarget(element);\n });\n\n function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$activeIndexes();\n var action = 'removeClass';\n if (angular.isArray(active)) {\n if (active.indexOf(index) !== -1) {\n action = 'addClass';\n }\n }\n else if (index === active) {\n action = 'addClass';\n }\n\n $animate[action](element, bsCollapseCtrl.$options.activeClass);\n }\n\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.datepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$datepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'datepicker',\n prefixClass: 'datepicker',\n placement: 'bottom-left',\n template: 'datepicker/datepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: false,\n dateType: 'date',\n dateFormat: 'shortDate',\n timezone: null,\n modelDateFormat: null,\n dayFormat: 'dd',\n monthFormat: 'MMM',\n yearFormat: 'yyyy',\n monthTitleFormat: 'MMMM yyyy',\n yearTitleFormat: 'yyyy',\n strictFormat: false,\n autoclose: false,\n minDate: -Infinity,\n maxDate: +Infinity,\n startView: 0,\n minView: 0,\n startWeek: 0,\n daysOfWeekDisabled: '',\n iconLeft: 'glyphicon glyphicon-chevron-left',\n iconRight: 'glyphicon glyphicon-chevron-right'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function DatepickerFactory(element, controller, config) {\n\n var $datepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $datepicker.$options;\n var scope = $datepicker.$scope;\n if(options.startView) options.startView -= options.minView;\n\n // View vars\n\n var pickerViews = datepickerViews($datepicker);\n $datepicker.$views = pickerViews.views;\n var viewDate = pickerViews.viewDate;\n scope.$mode = options.startView;\n scope.$iconLeft = options.iconLeft;\n scope.$iconRight = options.iconRight;\n var $picker = $datepicker.$views[scope.$mode];\n\n // Scope methods\n\n scope.$select = function(date) {\n $datepicker.select(date);\n };\n scope.$selectPane = function(value) {\n $datepicker.$selectPane(value);\n };\n scope.$toggleMode = function() {\n $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);\n };\n\n // Public methods\n\n $datepicker.update = function(date) {\n // console.warn('$datepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $datepicker.$date = date;\n $picker.update.call($picker, date);\n }\n // Build only if pristine\n $datepicker.$build(true);\n };\n\n $datepicker.updateDisabledDates = function(dateRanges) {\n options.disabledDateRanges = dateRanges;\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);\n }\n };\n\n $datepicker.select = function(date, keep) {\n // console.warn('$datepicker.select', date, scope.$mode);\n if(!angular.isDate(controller.$dateValue)) controller.$dateValue = new Date(date);\n if(!scope.$mode || keep) {\n controller.$setViewValue(angular.copy(date));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $datepicker.hide(true); });\n }\n } else {\n angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});\n $datepicker.setMode(scope.$mode - 1);\n $datepicker.$build();\n }\n };\n\n $datepicker.setMode = function(mode) {\n // console.warn('$datepicker.setMode', mode);\n scope.$mode = mode;\n $picker = $datepicker.$views[scope.$mode];\n $datepicker.$build();\n };\n\n // Protected methods\n\n $datepicker.$build = function(pristine) {\n // console.warn('$datepicker.$build() viewDate=%o', viewDate);\n if(pristine === true && $picker.built) return;\n if(pristine === false && !$picker.built) return;\n $picker.build.call($picker);\n };\n\n $datepicker.$updateSelected = function() {\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], updateSelected);\n }\n };\n\n $datepicker.$isSelected = function(date) {\n return $picker.isSelected(date);\n };\n\n $datepicker.$setDisabledEl = function(el) {\n el.disabled = $picker.isDisabled(el.date);\n };\n\n $datepicker.$selectPane = function(value) {\n var steps = $picker.steps;\n // set targetDate to first day of month to avoid problems with\n // date values rollover. This assumes the viewDate does not\n // depend on the day of the month\n var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));\n angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});\n $datepicker.$build();\n };\n\n $datepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $datepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n if(evt.keyCode === 13) {\n if(!scope.$mode) {\n return $datepicker.hide(true);\n } else {\n return scope.$apply(function() { $datepicker.setMode(scope.$mode - 1); });\n }\n }\n\n // Navigate with keyboard\n $picker.onKeyDown(evt);\n parentScope.$digest();\n };\n\n // Private\n\n function updateSelected(el) {\n el.selected = $datepicker.$isSelected(el.date);\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $datepicker.init;\n $datepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'date');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $datepicker.destroy;\n $datepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $datepicker.show;\n $datepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // if $datepicker is no longer showing, don't setup events\n if(!$datepicker.$isShown) return;\n $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $datepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $datepicker.hide;\n $datepicker.hide = function(blur) {\n if(!$datepicker.$isShown) return;\n $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $datepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $datepicker;\n\n }\n\n DatepickerFactory.defaults = defaults;\n return DatepickerFactory;\n\n };\n\n })\n\n .directive('bsDatepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {\n\n var defaults = $datepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'timezone', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!datepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);\n newValue === true ? datepicker.show() : datepicker.hide();\n });\n\n // Initialize datepicker\n var datepicker = $datepicker(element, controller, options);\n options = datepicker.$options;\n // Set expected iOS format\n if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';\n\n var lang = options.lang;\n\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n // Observe attributes for changes\n angular.forEach(['minDate', 'maxDate'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n // console.warn('attr.$observe(%s)=%o', key, newValue);\n datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);\n // Build only if dirty\n !isNaN(datepicker.$options[key]) && datepicker.$build(false);\n validateAgainstMinMaxDate(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n datepicker.update(controller.$dateValue);\n }, true);\n\n // Normalize undefined/null/empty array,\n // so that we don't treat changing from undefined->null as a change.\n function normalizeDateRanges(ranges) {\n if (!ranges || !ranges.length) return null;\n return ranges;\n }\n\n if (angular.isDefined(attr.disabledDates)) {\n scope.$watch(attr.disabledDates, function(disabledRanges, previousValue) {\n disabledRanges = normalizeDateRanges(disabledRanges);\n previousValue = normalizeDateRanges(previousValue);\n\n if (disabledRanges) {\n datepicker.updateDisabledDates(disabledRanges);\n }\n });\n }\n\n function validateAgainstMinMaxDate(parsedDate) {\n if (!angular.isDate(parsedDate)) return;\n var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;\n var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(isValid) controller.$dateValue = parsedDate;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n controller.$setValidity('date', true);\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n return null;\n }\n var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedDate || isNaN(parsedDate.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxDate(parsedDate);\n }\n\n if(options.dateType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedDate, options.timezone, true);\n return formatDate(date, options.modelDateFormat || options.dateFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.dateType === 'number') {\n return date.getTime();\n } else if(options.dateType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.dateType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.dateType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelDateFormat);\n } else if(options.dateType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) {\n // var today = new Date();\n // date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n // }\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getDateFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getDateFormattedString());\n };\n\n function getDateFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(datepicker) datepicker.destroy();\n options = null;\n datepicker = null;\n });\n\n }\n };\n\n })\n\n .provider('datepickerViews', function() {\n\n var defaults = this.defaults = {\n dayFormat: 'dd',\n daySplit: 7\n };\n\n // Split array into smaller arrays\n function split(arr, size) {\n var arrays = [];\n while(arr.length > 0) {\n arrays.push(arr.splice(0, size));\n }\n return arrays;\n }\n\n // Modulus operator\n function mod(n, m) {\n return ((n % m) + m) % m;\n }\n\n this.$get = function($dateFormatter, $dateParser, $sce) {\n\n return function(picker) {\n\n var scope = picker.$scope;\n var options = picker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n var weekDaysLabelsHtml = $sce.trustAsHtml('<th class=\"dow text-center\">' + weekDaysLabels.join('</th><th class=\"dow text-center\">') + '</th>');\n\n var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n\n var views = [{\n format: options.dayFormat,\n split: 7,\n steps: { month: 1 },\n update: function(date, force) {\n if(!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getDate() !== viewDate.date || date.getDate() === 1) {\n // chaging picker current month will cause viewDate.date to be set to first day of the month,\n // in $datepicker.$selectPane, so picker would not update selected day display if\n // user picks first day of the new month.\n // As a workaround, we are always forcing update when picked date is first day of month.\n viewDate.date = picker.$date.getDate();\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5), firstDateOffset = firstDate.getTimezoneOffset();\n var today = dateParser.timezoneOffsetAdjust(new Date(), options.timezone).toDateString();\n // Handle daylight time switch\n if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);\n var days = [], day;\n for(var i = 0; i < 42; i++) { // < 7 * 6\n day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));\n days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n }\n scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);\n scope.showLabels = true;\n scope.labels = weekDaysLabelsHtml;\n scope.rows = split(days, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();\n },\n isDisabled: function(date) {\n var time = date.getTime();\n\n // Disabled because of min/max date.\n if (time < options.minDate || time > options.maxDate) return true;\n\n // Disabled due to being a disabled day of the week\n if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;\n\n // Disabled because of disabled date range.\n if (options.disabledDateRanges) {\n for (var i = 0; i < options.disabledDateRanges.length; i++) {\n if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {\n return true;\n }\n }\n }\n\n return false;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualTime = picker.$date.getTime();\n var newDate;\n\n if(evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);\n else if(evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);\n else if(evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);\n else if(evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'month',\n format: options.monthFormat,\n split: 4,\n steps: { year: 1 },\n update: function(date, force) {\n if(!this.built || date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstMonth = new Date(viewDate.year, 0, 1);\n var months = [], month;\n for (var i = 0; i < 12; i++) {\n month = new Date(viewDate.year, i, 1);\n months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n }\n scope.title = formatDate(month, options.yearTitleFormat);\n scope.showLabels = false;\n scope.rows = split(months, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualMonth = picker.$date.getMonth();\n var newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setMonth(actualMonth - 1);\n else if(evt.keyCode === 38) newDate.setMonth(actualMonth - 4);\n else if(evt.keyCode === 39) newDate.setMonth(actualMonth + 1);\n else if(evt.keyCode === 40) newDate.setMonth(actualMonth + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'year',\n format: options.yearFormat,\n split: 4,\n steps: { year: 12 },\n update: function(date, force) {\n if(!this.built || force || parseInt(date.getFullYear()/20, 10) !== parseInt(viewDate.year/20, 10)) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstYear = viewDate.year - viewDate.year % (this.split * 3);\n var years = [], year;\n for (var i = 0; i < 12; i++) {\n year = new Date(firstYear + i, 0, 1);\n years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});\n }\n scope.title = years[0].label + '-' + years[years.length - 1].label;\n scope.showLabels = false;\n scope.rows = split(years, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear() + 1, 0, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualYear = picker.$date.getFullYear(),\n newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setYear(actualYear - 1);\n else if(evt.keyCode === 38) newDate.setYear(actualYear - 4);\n else if(evt.keyCode === 39) newDate.setYear(actualYear + 1);\n else if(evt.keyCode === 40) newDate.setYear(actualYear + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }];\n\n return {\n views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,\n viewDate: viewDate\n };\n\n };\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$dropdown', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'dropdown',\n prefixEvent: 'dropdown',\n placement: 'bottom-left',\n template: 'dropdown/dropdown.tpl.html',\n trigger: 'click',\n container: false,\n keyboard: true,\n html: false,\n delay: 0\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;\n\n function DropdownFactory(element, config) {\n\n var $dropdown = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n $dropdown = $tooltip(element, options);\n var parentEl = element.parent();\n\n // Protected methods\n\n $dropdown.$onKeyDown = function(evt) {\n if (!/(38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Retrieve focused index\n var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));\n if(!items.length) return;\n var index;\n angular.forEach(items, function(el, i) {\n if(matchesSelector && matchesSelector.call(el, ':focus')) index = i;\n });\n\n // Navigate with keyboard\n if(evt.keyCode === 38 && index > 0) index--;\n else if(evt.keyCode === 40 && index < items.length - 1) index++;\n else if(angular.isUndefined(index)) index = 0;\n items.eq(index)[0].focus();\n\n };\n\n // Overrides\n\n var show = $dropdown.show;\n $dropdown.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n options.keyboard && $dropdown.$element && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n bodyEl.on('click', onBodyClick);\n }, 0, false);\n parentEl.hasClass('dropdown') && parentEl.addClass('open');\n };\n\n var hide = $dropdown.hide;\n $dropdown.hide = function() {\n if(!$dropdown.$isShown) return;\n options.keyboard && $dropdown.$element && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n bodyEl.off('click', onBodyClick);\n parentEl.hasClass('dropdown') && parentEl.removeClass('open');\n hide();\n };\n\n var destroy = $dropdown.destroy;\n $dropdown.destroy = function() {\n bodyEl.off('click', onBodyClick);\n destroy();\n };\n\n // Private functions\n\n function onBodyClick(evt) {\n if(evt.target === element[0]) return;\n return evt.target !== element[0] && $dropdown.hide();\n }\n\n return $dropdown;\n\n }\n\n return DropdownFactory;\n\n };\n\n })\n\n .directive('bsDropdown', function($window, $sce, $dropdown) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as an object\n attr.bsDropdown && scope.$watch(attr.bsDropdown, function(newValue, oldValue) {\n scope.content = newValue;\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!dropdown || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(dropdown),?/i);\n newValue === true ? dropdown.show() : dropdown.hide();\n });\n\n // Initialize dropdown\n var dropdown = $dropdown(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (dropdown) dropdown.destroy();\n options = null;\n dropdown = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.button', [])\n\n .provider('$button', function() {\n\n var defaults = this.defaults = {\n activeClass:'active',\n toggleEvent:'click'\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsCheckboxGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"checkbox\"]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.attr('bs-checkbox', '');\n childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));\n });\n }\n\n };\n\n })\n\n .directive('bsCheckbox', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support label > input[type=\"checkbox\"]\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;\n if(constantValueRegExp.test(attr.trueValue)) {\n trueValue = scope.$eval(attr.trueValue);\n }\n var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;\n if(constantValueRegExp.test(attr.falseValue)) {\n falseValue = scope.$eval(attr.falseValue);\n }\n\n // Parse exotic values\n var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';\n if(hasExoticValues) {\n controller.$parsers.push(function(viewValue) {\n // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue);\n return viewValue ? trueValue : falseValue;\n });\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n return angular.equals(modelValue, trueValue);\n });\n // Fix rendering for exotic values\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n controller.$render();\n });\n }\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, trueValue);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n if(!isInput) {\n controller.$setViewValue(!activeElement.hasClass('active'));\n }\n if(!hasExoticValues) {\n controller.$render();\n }\n });\n });\n\n }\n\n };\n\n })\n\n .directive('bsRadioGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"radio\"]');\n angular.forEach(children, function(child) {\n angular.element(child).attr('bs-radio', '');\n angular.element(child).attr('ng-model', attr.ngModel);\n });\n }\n\n };\n\n })\n\n .directive('bsRadio', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support `label > input[type=\"radio\"]` markup\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var value;\n attr.$observe('value', function(v) {\n value = constantValueRegExp.test(v) ? scope.$eval(v) : v;\n controller.$render();\n });\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, value);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n controller.$setViewValue(value);\n controller.$render();\n });\n });\n\n }\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dateFormatter', [])\n\n .service('$dateFormatter', function($locale, dateFilter) {\n\n // The unused `lang` arguments are on purpose. The default implementation does not\n // use them and it always uses the locale loaded into the `$locale` service.\n // Custom implementations might use it, thus allowing different directives to\n // have different languages.\n\n this.getDefaultLocale = function() {\n return $locale.id;\n };\n\n // Format is either a data format name, e.g. \"shortTime\" or \"fullDate\", or a date format\n // Return either the corresponding date format or the given date format.\n this.getDatetimeFormat = function(format, lang) {\n return $locale.DATETIME_FORMATS[format] || format;\n };\n\n this.weekdaysShort = function(lang) {\n return $locale.DATETIME_FORMATS.SHORTDAY;\n };\n\n function splitTimeFormat(format) {\n return /(h+)([:\\.])?(m+)([:\\.])?(s*)[ ]?(a?)/i.exec(format).slice(1);\n }\n\n // h:mm a => h\n this.hoursFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[0];\n };\n\n // h:mm a => mm\n this.minutesFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[2];\n };\n\n // h:mm:ss a => ss\n this.secondsFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => :\n this.timeSeparator = function(timeFormat) {\n return splitTimeFormat(timeFormat)[1];\n };\n\n // h:mm:ss a => true, h:mm a => false\n this.showSeconds = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => true, H.mm => false\n this.showAM = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[5];\n };\n\n this.formatDate = function(date, format, lang, timezone){\n return dateFilter(date, format, timezone);\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dateParser', [])\n\n.provider('$dateParser', function($localeProvider) {\n\n // define a custom ParseDate object to use instead of native Date\n // to avoid date values wrapping when setting date component values\n function ParseDate() {\n this.year = 1970;\n this.month = 0;\n this.day = 1;\n this.hours = 0;\n this.minutes = 0;\n this.seconds = 0;\n this.milliseconds = 0;\n }\n\n ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };\n ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };\n ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };\n ParseDate.prototype.setHours = function(value) { this.hours = value; };\n ParseDate.prototype.getHours = function() { return this.hours; };\n ParseDate.prototype.setDate = function(value) { this.day = value; };\n ParseDate.prototype.setMonth = function(value) { this.month = value; };\n ParseDate.prototype.setFullYear = function(value) { this.year = value; };\n ParseDate.prototype.fromDate = function(value) {\n this.year = value.getFullYear();\n this.month = value.getMonth();\n this.day = value.getDate();\n this.hours = value.getHours();\n this.minutes = value.getMinutes();\n this.seconds = value.getSeconds();\n this.milliseconds = value.getMilliseconds();\n return this;\n };\n\n ParseDate.prototype.toDate = function() {\n return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n };\n\n var proto = ParseDate.prototype;\n\n function noop() {\n }\n\n function isNumeric(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n function indexOfCaseInsensitive(array, value) {\n var len = array.length, str=value.toString().toLowerCase();\n for (var i=0; i<len; i++) {\n if (array[i].toLowerCase() === str) { return i; }\n }\n return -1; // Return -1 per the \"Array.indexOf()\" method.\n }\n\n var defaults = this.defaults = {\n format: 'shortDate',\n strict: false\n };\n\n this.$get = function($locale, dateFilter) {\n\n var DateParserFactory = function(config) {\n\n var options = angular.extend({}, defaults, config);\n\n var $dateParser = {};\n\n var regExpMap = {\n 'sss' : '[0-9]{3}',\n 'ss' : '[0-5][0-9]',\n 's' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n 'mm' : '[0-5][0-9]',\n 'm' : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n 'HH' : '[01][0-9]|2[0-3]',\n 'H' : options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]',\n 'hh' : '[0][1-9]|[1][012]',\n 'h' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n 'a' : 'AM|PM',\n 'EEEE' : $locale.DATETIME_FORMATS.DAY.join('|'),\n 'EEE' : $locale.DATETIME_FORMATS.SHORTDAY.join('|'),\n 'dd' : '0[1-9]|[12][0-9]|3[01]',\n 'd' : options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]',\n 'MMMM' : $locale.DATETIME_FORMATS.MONTH.join('|'),\n 'MMM' : $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n 'MM' : '0[1-9]|1[012]',\n 'M' : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n 'yyyy' : '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',\n 'yy' : '[0-9]{2}',\n 'y' : options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}',\n };\n\n var setFnMap = {\n 'sss' : proto.setMilliseconds,\n 'ss' : proto.setSeconds,\n 's' : proto.setSeconds,\n 'mm' : proto.setMinutes,\n 'm' : proto.setMinutes,\n 'HH' : proto.setHours,\n 'H' : proto.setHours,\n 'hh' : proto.setHours,\n 'h' : proto.setHours,\n 'EEEE' : noop,\n 'EEE' : noop,\n 'dd' : proto.setDate,\n 'd' : proto.setDate,\n 'a' : function(value) { var hours = this.getHours() % 12; return this.setHours(value.match(/pm/i) ? hours + 12 : hours); },\n 'MMMM' : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.MONTH, value)); },\n 'MMM' : function(value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.SHORTMONTH, value)); },\n 'MM' : function(value) { return this.setMonth(1 * value - 1); },\n 'M' : function(value) { return this.setMonth(1 * value - 1); },\n 'yyyy' : proto.setFullYear,\n 'yy' : function(value) { return this.setFullYear(2000 + 1 * value); },\n 'y' : proto.setFullYear\n };\n\n var regex, setMap;\n\n $dateParser.init = function() {\n $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;\n regex = regExpForFormat($dateParser.$format);\n setMap = setMapForFormat($dateParser.$format);\n };\n\n $dateParser.isValid = function(date) {\n if(angular.isDate(date)) return !isNaN(date.getTime());\n return regex.test(date);\n };\n\n $dateParser.parse = function(value, baseDate, format, timezone) {\n // check for date format special names\n if(format) format = $locale.DATETIME_FORMATS[format] || format;\n if(angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format, timezone);\n var formatRegex = format ? regExpForFormat(format) : regex;\n var formatSetMap = format ? setMapForFormat(format) : setMap;\n var matches = formatRegex.exec(value);\n if(!matches) return false;\n // use custom ParseDate object to set parsed values\n var date = baseDate && !isNaN(baseDate.getTime()) ? new ParseDate().fromDate(baseDate) : new ParseDate().fromDate(new Date(1970, 0, 1, 0));\n for(var i = 0; i < matches.length - 1; i++) {\n formatSetMap[i] && formatSetMap[i].call(date, matches[i+1]);\n }\n // convert back to native Date object\n var newDate = date.toDate();\n\n // check new native Date object for day values overflow\n if (parseInt(date.day, 10) !== newDate.getDate()) {\n return false;\n }\n\n return newDate;\n };\n\n $dateParser.getDateForAttribute = function(key, value) {\n var date;\n\n if(value === 'today') {\n var today = new Date();\n date = new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, (key === 'minDate' ? 0 : -1));\n } else if(angular.isString(value) && value.match(/^\".+\"$/)) { // Support {{ dateObj }}\n date = new Date(value.substr(1, value.length - 2));\n } else if(isNumeric(value)) {\n date = new Date(parseInt(value, 10));\n } else if (angular.isString(value) && 0 === value.length) { // Reset date\n date = key === 'minDate' ? -Infinity : +Infinity;\n } else {\n date = new Date(value);\n }\n\n return date;\n };\n\n $dateParser.getTimeForAttribute = function(key, value) {\n var time;\n\n if(value === 'now') {\n time = new Date().setFullYear(1970, 0, 1);\n } else if(angular.isString(value) && value.match(/^\".+\"$/)) {\n time = new Date(value.substr(1, value.length - 2)).setFullYear(1970, 0, 1);\n } else if(isNumeric(value)) {\n time = new Date(parseInt(value, 10)).setFullYear(1970, 0, 1);\n } else if (angular.isString(value) && 0 === value.length) { // Reset time\n time = key === 'minTime' ? -Infinity : +Infinity;\n } else {\n time = $dateParser.parse(value, new Date(1970, 0, 1, 0));\n }\n\n return time;\n };\n\n /* Handle switch to/from daylight saving.\n * Hours may be non-zero on daylight saving cut-over:\n * > 12 when midnight changeover, but then cannot generate\n * midnight datetime, so jump to 1AM, otherwise reset.\n * @param date (Date) the date to check\n * @return (Date) the corrected date\n *\n * __ copied from jquery ui datepicker __\n */\n $dateParser.daylightSavingAdjust = function(date) {\n if (!date) {\n return null;\n }\n date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n return date;\n };\n\n /* Correct the date for timezone offset.\n * @param date (Date) the date to adjust\n * @param timezone (string) the timezone to adjust for\n * @param undo (boolean) to add or subtract timezone offset\n * @return (Date) the corrected date\n */\n $dateParser.timezoneOffsetAdjust = function(date, timezone, undo) {\n if (!date) {\n return null;\n }\n // Right now, only 'UTC' is supported.\n if (timezone && timezone === 'UTC') {\n date = new Date(date.getTime());\n date.setMinutes(date.getMinutes() + (undo?-1:1)*date.getTimezoneOffset());\n }\n return date;\n };\n\n // Private functions\n\n function setMapForFormat(format) {\n var keys = Object.keys(setFnMap), i;\n var map = [], sortedMap = [];\n // Map to setFn\n var clonedFormat = format;\n for(i = 0; i < keys.length; i++) {\n if(format.split(keys[i]).length > 1) {\n var index = clonedFormat.search(keys[i]);\n format = format.split(keys[i]).join('');\n if(setFnMap[keys[i]]) {\n map[index] = setFnMap[keys[i]];\n }\n }\n }\n // Sort result map\n angular.forEach(map, function(v) {\n // conditional required since angular.forEach broke around v1.2.21\n // related pr: https://github.com/angular/angular.js/pull/8525\n if(v) sortedMap.push(v);\n });\n return sortedMap;\n }\n\n function escapeReservedSymbols(text) {\n return text.replace(/\\//g, '[\\\\/]').replace('/-/g', '[-]').replace(/\\./g, '[.]').replace(/\\\\s/g, '[\\\\s]');\n }\n\n function regExpForFormat(format) {\n var keys = Object.keys(regExpMap), i;\n\n var re = format;\n // Abstract replaces to avoid collisions\n for(i = 0; i < keys.length; i++) {\n re = re.split(keys[i]).join('${' + i + '}');\n }\n // Replace abstracted values\n for(i = 0; i < keys.length; i++) {\n re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');\n }\n format = escapeReservedSymbols(format);\n\n return new RegExp('^' + re + '$', ['i']);\n }\n\n $dateParser.init();\n return $dateParser;\n\n };\n\n return DateParserFactory;\n\n };\n\n});\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.debounce', [])\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L693\n.factory('debounce', function($timeout) {\n return function(func, wait, immediate) {\n var timeout = null;\n return function() {\n var context = this,\n args = arguments,\n callNow = immediate && !timeout;\n if(timeout) {\n $timeout.cancel(timeout);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(!immediate) {\n func.apply(context, args);\n }\n }, wait, false);\n if(callNow) {\n func.apply(context, args);\n }\n return timeout;\n };\n };\n})\n\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L661\n.factory('throttle', function($timeout) {\n return function(func, wait, options) {\n var timeout = null;\n options || (options = {});\n return function() {\n var context = this,\n args = arguments;\n if(!timeout) {\n if(options.leading !== false) {\n func.apply(context, args);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(options.trailing !== false) {\n func.apply(context, args);\n }\n }, wait, false);\n }\n };\n };\n});\n\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n .factory('dimensions', function($document, $window) {\n\n var jqLite = angular.element;\n var fn = {};\n\n /**\n * Test the element nodeName\n * @param element\n * @param name\n */\n var nodeName = fn.nodeName = function(element, name) {\n return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();\n };\n\n /**\n * Returns the element computed style\n * @param element\n * @param prop\n * @param extra\n */\n fn.css = function(element, prop, extra) {\n var value;\n if (element.currentStyle) { //IE\n value = element.currentStyle[prop];\n } else if (window.getComputedStyle) {\n value = window.getComputedStyle(element)[prop];\n } else {\n value = element.style[prop];\n }\n return extra === true ? parseFloat(value) || 0 : value;\n };\n\n /**\n * Provides read-only equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.offset = function(element) {\n var boxRect = element.getBoundingClientRect();\n var docElement = element.ownerDocument;\n return {\n width: boxRect.width || element.offsetWidth,\n height: boxRect.height || element.offsetHeight,\n top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),\n left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)\n };\n };\n \n /**\n * Provides set equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip\n * @url http://api.jquery.com/offset/\n * @param element\n * @param options\n * @param i\n */\n fn.setOffset = function (element, options, i) {\n var curPosition,\n curLeft,\n curCSSTop,\n curTop,\n curOffset,\n curCSSLeft,\n calculatePosition,\n position = fn.css(element, 'position'),\n curElem = angular.element(element),\n props = {};\n \n // Set position first, in-case top/left are set even on static elem\n if (position === 'static') {\n element.style.position = 'relative';\n }\n \n curOffset = fn.offset(element);\n curCSSTop = fn.css(element, 'top');\n curCSSLeft = fn.css(element, 'left');\n calculatePosition = (position === 'absolute' || position === 'fixed') && \n (curCSSTop + curCSSLeft).indexOf('auto') > -1;\n \n // Need to be able to calculate position if either\n // top or left is auto and position is either absolute or fixed\n if (calculatePosition) {\n curPosition = fn.position(element);\n curTop = curPosition.top;\n curLeft = curPosition.left;\n } else {\n curTop = parseFloat(curCSSTop) || 0;\n curLeft = parseFloat(curCSSLeft) || 0;\n }\n \n if (angular.isFunction(options)) {\n options = options.call(element, i, curOffset);\n }\n \n if (options.top !== null ) {\n props.top = (options.top - curOffset.top) + curTop;\n }\n if ( options.left !== null ) {\n props.left = (options.left - curOffset.left) + curLeft;\n }\n\n if ('using' in options) {\n options.using.call(curElem, props);\n } else {\n curElem.css({\n top: props.top + 'px',\n left: props.left + 'px'\n });\n }\n };\n\n /**\n * Provides read-only equivalent of jQuery's position function\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.position = function(element) {\n\n var offsetParentRect = {top: 0, left: 0},\n offsetParentElement,\n offset;\n\n // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n if (fn.css(element, 'position') === 'fixed') {\n\n // We assume that getBoundingClientRect is available when computed position is fixed\n offset = element.getBoundingClientRect();\n\n } else {\n\n // Get *real* offsetParentElement\n offsetParentElement = offsetParent(element);\n\n // Get correct offsets\n offset = fn.offset(element);\n if (!nodeName(offsetParentElement, 'html')) {\n offsetParentRect = fn.offset(offsetParentElement);\n }\n\n // Add offsetParent borders\n offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);\n offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);\n }\n\n // Subtract parent offsets and element margins\n return {\n width: element.offsetWidth,\n height: element.offsetHeight,\n top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),\n left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)\n };\n\n };\n\n /**\n * Returns the closest, non-statically positioned offsetParent of a given element\n * @required-by fn.position\n * @param element\n */\n var offsetParent = function offsetParentElement(element) {\n var docElement = element.ownerDocument;\n var offsetParent = element.offsetParent || docElement;\n if(nodeName(offsetParent, '#document')) return docElement.documentElement;\n while(offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {\n offsetParent = offsetParent.offsetParent;\n }\n return offsetParent || docElement.documentElement;\n };\n\n /**\n * Provides equivalent of jQuery's height function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/height/\n * @param element\n * @param outer\n */\n fn.height = function(element, outer) {\n var value = element.offsetHeight;\n if(outer) {\n value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);\n } else {\n value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);\n }\n return value;\n };\n\n /**\n * Provides equivalent of jQuery's width function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/width/\n * @param element\n * @param outer\n */\n fn.width = function(element, outer) {\n var value = element.offsetWidth;\n if(outer) {\n value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);\n } else {\n value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);\n }\n return value;\n };\n\n return fn;\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.parseOptions', [])\n\n .provider('$parseOptions', function() {\n\n var defaults = this.defaults = {\n 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+(.*?))?$/\n };\n\n this.$get = function($parse, $q) {\n\n function ParseOptionsFactory(attr, config) {\n\n var $parseOptions = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n $parseOptions.$values = [];\n\n // Private vars\n var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;\n\n $parseOptions.init = function() {\n $parseOptions.$match = match = attr.match(options.regexp);\n displayFn = $parse(match[2] || match[1]),\n valueName = match[4] || match[6],\n keyName = match[5],\n groupByFn = $parse(match[3] || ''),\n valueFn = $parse(match[2] ? match[1] : valueName),\n valuesFn = $parse(match[7]);\n };\n\n $parseOptions.valuesFn = function(scope, controller) {\n return $q.when(valuesFn(scope, controller))\n .then(function(values) {\n $parseOptions.$values = values ? parseValues(values, scope) : {};\n return $parseOptions.$values;\n });\n };\n\n $parseOptions.displayValue = function(modelValue) {\n var scope = {};\n scope[valueName] = modelValue;\n return displayFn(scope);\n };\n\n // Private functions\n\n function parseValues(values, scope) {\n return values.map(function(match, index) {\n var locals = {}, label, value;\n locals[valueName] = match;\n label = displayFn(scope, locals);\n value = valueFn(scope, locals);\n return {label: label, value: value, index: index};\n });\n }\n\n $parseOptions.init();\n return $parseOptions;\n\n }\n\n return ParseOptionsFactory;\n\n };\n\n });\n","'use strict';\n\n(angular.version.minor < 3 && angular.version.dot < 14) && angular.module('ng')\n\n.factory('$$rAF', function($window, $timeout) {\n\n var requestAnimationFrame = $window.requestAnimationFrame ||\n $window.webkitRequestAnimationFrame ||\n $window.mozRequestAnimationFrame;\n\n var cancelAnimationFrame = $window.cancelAnimationFrame ||\n $window.webkitCancelAnimationFrame ||\n $window.mozCancelAnimationFrame ||\n $window.webkitCancelRequestAnimationFrame;\n\n var rafSupported = !!requestAnimationFrame;\n var raf = rafSupported ?\n function(fn) {\n var id = requestAnimationFrame(fn);\n return function() {\n cancelAnimationFrame(id);\n };\n } :\n function(fn) {\n var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n return function() {\n $timeout.cancel(timer);\n };\n };\n\n raf.supported = rafSupported;\n\n return raf;\n\n});\n\n// .factory('$$animateReflow', function($$rAF, $document) {\n\n// var bodyEl = $document[0].body;\n\n// return function(fn) {\n// //the returned function acts as the cancellation function\n// return $$rAF(function() {\n// //the line below will force the browser to perform a repaint\n// //so that all the animated elements within the animation frame\n// //will be properly updated and drawn on screen. This is\n// //required to perform multi-class CSS based animations with\n// //Firefox. DO NOT REMOVE THIS LINE.\n// var a = bodyEl.offsetWidth + 1;\n// fn();\n// });\n// };\n\n// });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$modal', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n backdropAnimation: 'am-fade',\n prefixClass: 'modal',\n prefixEvent: 'modal',\n placement: 'top',\n template: 'modal/modal.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {\n\n var forEach = angular.forEach;\n var trim = String.prototype.trim;\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n var bodyElement = angular.element($window.document.body);\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n\n function ModalFactory(config) {\n\n var $modal = {};\n\n // Common vars\n var options = $modal.$options = angular.extend({}, defaults, config);\n $modal.$promise = fetchTemplate(options.template);\n var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(!options.element && !options.container) {\n options.container = 'body';\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $modal.$id = options.id || options.element && options.element.attr('id') || '';\n\n // Support scope as string options\n forEach(['title', 'content'], function(key) {\n if(options[key]) scope[key] = $sce.trustAsHtml(options[key]);\n });\n\n // Provide scope helpers\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $modal.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $modal.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $modal.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $modal.$isShown = scope.$isShown = false;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $modal.$promise = $modal.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);\n // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n if(!config.template) contentEl.next().remove();\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize modal\n var modalLinker, modalElement;\n var backdropElement = angular.element('<div class=\"' + options.prefixClass + '-backdrop\"/>');\n backdropElement.css({position:'fixed', top:'0px', left:'0px', bottom:'0px', right:'0px', 'z-index': 1038});\n $modal.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n modalLinker = $compile(template);\n $modal.init();\n });\n\n $modal.init = function() {\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n $modal.show();\n });\n }\n\n };\n\n $modal.destroy = function() {\n\n // Remove element\n if(modalElement) {\n modalElement.remove();\n modalElement = null;\n }\n if(backdropElement) {\n backdropElement.remove();\n backdropElement = null;\n }\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $modal.show = function() {\n if($modal.$isShown) return;\n\n var parent, after;\n if(angular.isElement(options.container)) {\n parent = options.container;\n after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;\n } else {\n if (options.container) {\n parent = findElement(options.container);\n after = parent[0] && parent[0].lastChild ? angular.element(parent[0].lastChild) : null;\n } else {\n parent = null;\n after = options.element;\n }\n }\n\n // Fetch a cloned element linked from template\n modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\n\n if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n return;\n }\n\n // Set the initial positioning.\n modalElement.css({display: 'block'}).addClass(options.placement);\n\n // Options: animation\n if(options.animation) {\n if(options.backdrop) {\n backdropElement.addClass(options.backdropAnimation);\n }\n modalElement.addClass(options.animation);\n }\n\n if(options.backdrop) {\n $animate.enter(backdropElement, bodyElement, null);\n }\n\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if(angular.version.minor <= 2) {\n $animate.enter(modalElement, parent, after, enterAnimateCallback);\n } else {\n $animate.enter(modalElement, parent, after).then(enterAnimateCallback);\n }\n\n $modal.$isShown = scope.$isShown = true;\n safeDigest(scope);\n // Focus once the enter-animation has started\n // Weird PhantomJS bug hack\n var el = modalElement[0];\n requestAnimationFrame(function() {\n el.focus();\n });\n\n bodyElement.addClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n }\n\n // Bind events\n if(options.backdrop) {\n modalElement.on('click', hideOnBackdropClick);\n backdropElement.on('click', hideOnBackdropClick);\n backdropElement.on('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.on('keyup', $modal.$onKeyUp);\n }\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $modal);\n }\n\n $modal.hide = function() {\n if(!$modal.$isShown) return;\n\n if(scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {\n return;\n }\n\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if(angular.version.minor <= 2) {\n $animate.leave(modalElement, leaveAnimateCallback);\n } else {\n $animate.leave(modalElement).then(leaveAnimateCallback);\n }\n\n if(options.backdrop) {\n $animate.leave(backdropElement);\n }\n $modal.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.backdrop) {\n modalElement.off('click', hideOnBackdropClick);\n backdropElement.off('click', hideOnBackdropClick);\n backdropElement.off('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.off('keyup', $modal.$onKeyUp);\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $modal);\n bodyElement.removeClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n }\n }\n\n $modal.toggle = function() {\n\n $modal.$isShown ? $modal.hide() : $modal.show();\n\n };\n\n $modal.focus = function() {\n modalElement[0].focus();\n };\n\n // Protected methods\n\n $modal.$onKeyUp = function(evt) {\n\n if (evt.which === 27 && $modal.$isShown) {\n $modal.hide();\n evt.stopPropagation();\n }\n\n };\n\n // Private methods\n\n function hideOnBackdropClick(evt) {\n if(evt.target !== evt.currentTarget) return;\n options.backdrop === 'static' ? $modal.focus() : $modal.hide();\n }\n\n function preventEventDefault(evt) {\n evt.preventDefault();\n }\n\n return $modal;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return ModalFactory;\n\n };\n\n })\n\n .directive('bsModal', function($window, $sce, $modal) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsModal && scope.$watch(attr.bsModal, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize modal\n var modal = $modal(options);\n\n // Trigger\n element.on(attr.trigger || 'click', modal.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (modal) modal.destroy();\n options = null;\n modal = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.navbar', [])\n\n .provider('$navbar', function() {\n\n var defaults = this.defaults = {\n activeClass: 'active',\n routeAttr: 'data-match-route',\n strict: false\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsNavbar', function($window, $location, $navbar) {\n\n var defaults = $navbar.defaults;\n\n return {\n restrict: 'A',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = angular.copy(defaults);\n angular.forEach(Object.keys(defaults), function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Watch for the $location\n scope.$watch(function() {\n\n return $location.path();\n\n }, function(newValue, oldValue) {\n\n var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');\n\n angular.forEach(liElements, function(li) {\n\n var liElement = angular.element(li);\n var pattern = liElement.attr(options.routeAttr).replace('/', '\\\\/');\n if(options.strict) {\n pattern = '^' + pattern + '$';\n }\n var regexp = new RegExp(pattern, 'i');\n\n if(regexp.test(newValue)) {\n liElement.addClass(options.activeClass);\n } else {\n liElement.removeClass(options.activeClass);\n }\n\n });\n\n });\n\n }\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$popover', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n // uncommenting the next two lines will break backwards compatability\n // prefixClass: 'popover',\n // prefixEvent: 'popover',\n container: false,\n target: false,\n placement: 'right',\n template: 'popover/popover.tpl.html',\n contentTemplate: false,\n trigger: 'click',\n keyboard: true,\n html: false,\n title: '',\n content: '',\n delay: 0,\n autoClose: false\n };\n\n this.$get = function($tooltip) {\n\n function PopoverFactory(element, config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n var $popover = $tooltip(element, options);\n\n // Support scope as string options [/*title, */content]\n if(options.content) {\n $popover.$scope.content = options.content;\n }\n\n return $popover;\n\n }\n\n return PopoverFactory;\n\n };\n\n })\n\n .directive('bsPopover', function($window, $sce, $popover) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'customClass', 'autoClose', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoClose'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n });\n });\n\n // Support scope as an object\n attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);\n newValue === true ? popover.show() : popover.hide();\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n popover.setViewport(newValue);\n });\n\n // Initialize popover\n var popover = $popover(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (popover) popover.destroy();\n options = null;\n popover = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', 'mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$scrollspy', function() {\n\n // Pool of registered spies\n var spies = this.$$spies = {};\n\n var defaults = this.defaults = {\n debounce: 150,\n throttle: 100,\n offset: 100\n };\n\n this.$get = function($window, $document, $rootScope, dimensions, debounce, throttle) {\n\n var windowEl = angular.element($window);\n var docEl = angular.element($document.prop('documentElement'));\n var bodyEl = angular.element($window.document.body);\n\n // Helper functions\n\n function nodeName(element, name) {\n return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();\n }\n\n function ScrollSpyFactory(config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n if(!options.element) options.element = bodyEl;\n var isWindowSpy = nodeName(options.element, 'body');\n var scrollEl = isWindowSpy ? windowEl : options.element;\n var scrollId = isWindowSpy ? 'window' : options.id;\n\n // Use existing spy\n if(spies[scrollId]) {\n spies[scrollId].$$count++;\n return spies[scrollId];\n }\n\n var $scrollspy = {};\n\n // Private vars\n var unbindViewContentLoaded, unbindIncludeContentLoaded;\n var trackedElements = $scrollspy.$trackedElements = [];\n var sortedElements = [];\n var activeTarget;\n var debouncedCheckPosition;\n var throttledCheckPosition;\n var debouncedCheckOffsets;\n var viewportHeight;\n var scrollTop;\n\n $scrollspy.init = function() {\n\n // Setup internal ref counter\n this.$$count = 1;\n\n // Bind events\n debouncedCheckPosition = debounce(this.checkPosition, options.debounce);\n throttledCheckPosition = throttle(this.checkPosition, options.throttle);\n scrollEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', debouncedCheckPosition);\n scrollEl.on('scroll', throttledCheckPosition);\n\n debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);\n unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);\n unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);\n debouncedCheckOffsets();\n\n // Register spy for reuse\n if(scrollId) {\n spies[scrollId] = $scrollspy;\n }\n\n };\n\n $scrollspy.destroy = function() {\n\n // Check internal ref counter\n this.$$count--;\n if(this.$$count > 0) {\n return;\n }\n\n // Unbind events\n scrollEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', debouncedCheckPosition);\n scrollEl.off('scroll', throttledCheckPosition);\n unbindViewContentLoaded();\n unbindIncludeContentLoaded();\n if (scrollId) {\n delete spies[scrollId];\n }\n };\n\n $scrollspy.checkPosition = function() {\n\n // Not ready yet\n if(!sortedElements.length) return;\n\n // Calculate the scroll position\n scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;\n\n // Calculate the viewport height for use by the components\n viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));\n\n // Activate first element if scroll is smaller\n if(scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {\n return $scrollspy.$activateElement(sortedElements[0]);\n }\n\n // Activate proper element\n for (var i = sortedElements.length; i--;) {\n if(angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) continue;\n if(activeTarget === sortedElements[i].target) continue;\n if(scrollTop < sortedElements[i].offsetTop) continue;\n if(sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) continue;\n return $scrollspy.$activateElement(sortedElements[i]);\n }\n\n };\n\n $scrollspy.checkPositionWithEventLoop = function() {\n // IE 9 throws an error if we use 'this' instead of '$scrollspy'\n // in this setTimeout call\n setTimeout($scrollspy.checkPosition, 1);\n };\n\n // Protected methods\n\n $scrollspy.$activateElement = function(element) {\n if(activeTarget) {\n var activeElement = $scrollspy.$getTrackedElement(activeTarget);\n if(activeElement) {\n activeElement.source.removeClass('active');\n if(nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {\n activeElement.source.parent().parent().removeClass('active');\n }\n }\n }\n activeTarget = element.target;\n element.source.addClass('active');\n if(nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {\n element.source.parent().parent().addClass('active');\n }\n };\n\n $scrollspy.$getTrackedElement = function(target) {\n return trackedElements.filter(function(obj) {\n return obj.target === target;\n })[0];\n };\n\n // Track offsets behavior\n\n $scrollspy.checkOffsets = function() {\n\n angular.forEach(trackedElements, function(trackedElement) {\n var targetElement = document.querySelector(trackedElement.target);\n trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;\n if(options.offset && trackedElement.offsetTop !== null) trackedElement.offsetTop -= options.offset * 1;\n });\n\n sortedElements = trackedElements\n .filter(function(el) {\n return el.offsetTop !== null;\n })\n .sort(function(a, b) {\n return a.offsetTop - b.offsetTop;\n });\n\n debouncedCheckPosition();\n\n };\n\n $scrollspy.trackElement = function(target, source) {\n trackedElements.push({target: target, source: source});\n };\n\n $scrollspy.untrackElement = function(target, source) {\n var toDelete;\n for (var i = trackedElements.length; i--;) {\n if(trackedElements[i].target === target && trackedElements[i].source === source) {\n toDelete = i;\n break;\n }\n }\n trackedElements = trackedElements.splice(toDelete, 1);\n };\n\n $scrollspy.activate = function(i) {\n trackedElements[i].addClass('active');\n };\n\n // Initialize plugin\n\n $scrollspy.init();\n return $scrollspy;\n\n }\n\n return ScrollSpyFactory;\n\n };\n\n })\n\n .directive('bsScrollspy', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'EAC',\n link: function postLink(scope, element, attr) {\n\n var options = {scope: scope};\n angular.forEach(['offset', 'target'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n var scrollspy = $scrollspy(options);\n scrollspy.trackElement(options.target, element);\n\n scope.$on('$destroy', function() {\n if (scrollspy) {\n scrollspy.untrackElement(options.target, element);\n scrollspy.destroy();\n }\n options = null;\n scrollspy = null;\n });\n\n }\n };\n\n })\n\n\n .directive('bsScrollspyList', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'A',\n compile: function postLink(element, attr) {\n var children = element[0].querySelectorAll('li > a[href]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));\n });\n }\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$select', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'select',\n prefixEvent: '$select',\n placement: 'bottom-left',\n template: 'select/select.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n multiple: false,\n allNoneButtons: false,\n sort: true,\n caretHtml: '&nbsp;<span class=\"caret\"></span>',\n placeholder: 'Choose among the following...',\n allText: 'All',\n noneText: 'None',\n maxLength: 3,\n maxLengthHtml: 'selected',\n iconCheckmark: 'glyphicon glyphicon-ok'\n };\n\n this.$get = function($window, $document, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n\n function SelectFactory(element, controller, config) {\n\n var $select = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $select = $tooltip(element, options);\n var scope = $select.$scope;\n\n scope.$matches = [];\n if (options.multiple) {\n scope.$activeIndex = [];\n }\n else {\n scope.$activeIndex = -1;\n }\n scope.$isMultiple = options.multiple;\n scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n scope.$iconCheckmark = options.iconCheckmark;\n scope.$allText = options.allText;\n scope.$noneText = options.noneText;\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $select.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $select.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $select.$isVisible();\n };\n\n scope.$isActive = function(index) {\n return $select.$isActive(index);\n };\n\n scope.$selectAll = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (!scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n scope.$selectNone = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n // Public methods\n\n $select.update = function(matches) {\n scope.$matches = matches;\n $select.$updateActiveIndex();\n };\n\n $select.activate = function(index) {\n if(options.multiple) {\n $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);\n if(options.sort) scope.$activeIndex.sort(function(a, b) { return a - b; }); // use numeric sort instead of default sort\n } else {\n scope.$activeIndex = index;\n }\n return scope.$activeIndex;\n };\n\n $select.select = function(index) {\n var value = scope.$matches[index].value;\n scope.$apply(function() {\n $select.activate(index);\n if(options.multiple) {\n controller.$setViewValue(scope.$activeIndex.map(function(index) {\n return scope.$matches[index].value;\n }));\n } else {\n controller.$setViewValue(value);\n // Hide if single select\n $select.hide();\n }\n });\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $select);\n };\n\n // Protected methods\n\n $select.$updateActiveIndex = function() {\n if(controller.$modelValue && scope.$matches.length) {\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n scope.$activeIndex = controller.$modelValue.map(function(value) {\n return $select.$getIndex(value);\n });\n } else {\n scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n }\n } else if(scope.$activeIndex >= scope.$matches.length) {\n scope.$activeIndex = options.multiple ? [] : 0;\n }\n };\n\n $select.$isVisible = function() {\n if(!options.minLength || !controller) {\n return scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && controller.$viewValue.length >= options.minLength;\n };\n\n $select.$isActive = function(index) {\n if(options.multiple) {\n return scope.$activeIndex.indexOf(index) !== -1;\n } else {\n return scope.$activeIndex === index;\n }\n };\n\n $select.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $select.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n targetEl.triggerHandler('click');\n }\n };\n\n $select.$onKeyDown = function(evt) {\n if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // release focus on tab\n if (options.multiple && evt.keyCode === 9) {\n return $select.hide();\n }\n\n // Select with enter\n if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n return $select.select(scope.$activeIndex);\n }\n\n if (!options.multiple) {\n // Navigate with keyboard\n if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 38 && scope.$activeIndex < 0) scope.$activeIndex = scope.$matches.length - 1;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n }\n };\n\n // Overrides\n\n var _show = $select.show;\n $select.show = function() {\n _show();\n if(options.multiple) {\n $select.$element.addClass('select-multiple');\n }\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $select.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $select.hide;\n $select.hide = function() {\n if(!options.multiple && !controller.$modelValue) {\n scope.$activeIndex = -1;\n }\n $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $select.$onKeyDown);\n }\n _hide(true);\n };\n\n return $select;\n\n }\n\n SelectFactory.defaults = defaults;\n return SelectFactory;\n\n };\n\n })\n\n .directive('bsSelect', function($window, $parse, $q, $select, $parseOptions) {\n\n var defaults = $select.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, placeholder: defaults.placeholder};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'placeholder', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id', 'sort', 'caretHtml', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'allNoneButtons', 'sort'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Only parse data-multiple. Angular sets existence attributes to true (multiple/required/etc), they apply this\n // to data-multiple as well for some reason, so we'll parse this ourselves and disregard multiple\n var dataMultiple = element.attr('data-multiple');\n if(angular.isDefined(dataMultiple)) {\n if(falseValueRegExp.test(dataMultiple))\n options.multiple = false;\n else\n options.multiple = dataMultiple;\n }\n\n // Add support for select markup\n if(element[0].nodeName.toLowerCase() === 'select') {\n var inputEl = element;\n inputEl.css('display', 'none');\n element = angular.element('<button type=\"button\" class=\"btn btn-default\"></button>');\n inputEl.after(element);\n }\n\n // Build proper bsOptions\n var parsedOptions = $parseOptions(attr.bsOptions);\n\n // Initialize select\n var select = $select(element, controller, options);\n\n // Watch bsOptions values before filtering for changes\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n scope.$watchCollection(watchedOptions, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n select.update(values);\n controller.$render();\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n select.$updateActiveIndex();\n controller.$render();\n }, true);\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var selected, index;\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n selected = controller.$modelValue.map(function(value) {\n index = select.$getIndex(value);\n return angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }).filter(angular.isDefined);\n if(selected.length > (options.maxLength || defaults.maxLength)) {\n selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml);\n } else {\n selected = selected.join(', ');\n }\n } else {\n index = select.$getIndex(controller.$modelValue);\n selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }\n element.html((selected ? selected : options.placeholder) + (options.caretHtml ? options.caretHtml : defaults.caretHtml));\n };\n\n if(options.multiple){\n controller.$isEmpty = function(value){\n return !value || value.length === 0;\n };\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (select) select.destroy();\n options = null;\n select = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.tab', [])\n\n .provider('$tab', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n template: 'tab/tab.tpl.html',\n navClass: 'nav-tabs',\n activeClass: 'active'\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'navClass', 'activeClass'], function(key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // Publish options on scope\n $scope.$navClass = self.$options.navClass;\n $scope.$activeClass = self.$options.activeClass;\n\n self.$panes = $scope.$panes = [];\n\n // Please use $activePaneChangeListeners if you use `bsActivePane`\n // Because we removed `ngModel` as default, we rename viewChangeListeners to\n // activePaneChangeListeners to make more sense.\n self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n if(angular.isUndefined(self.$panes.$active)) {\n $scope.$setActive(pane.name || 0);\n }\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var active = self.$panes.$active;\n var activeIndex;\n if(angular.isString(active)) {\n activeIndex = self.$panes.map(function(pane) {\n return pane.name;\n }).indexOf(active);\n } else {\n activeIndex = self.$panes.$active;\n }\n\n // remove pane from $panes array\n self.$panes.splice(index, 1);\n\n if (index < activeIndex) {\n // we removed a pane before the active pane, so we need to\n // decrement the active pane index\n activeIndex--;\n }\n else if (index === activeIndex && activeIndex === self.$panes.length) {\n // we remove the active pane and it was the one at the end,\n // so select the previous one\n activeIndex--;\n }\n if(activeIndex >= 0 && activeIndex < self.$panes.length) {\n self.$setActive(self.$panes[activeIndex].name || activeIndex);\n } else {\n self.$setActive();\n }\n };\n\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$activePaneChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$isActive = $scope.$isActive = function($pane, $index) {\n return self.$panes.$active === $pane.name || self.$panes.$active === $index;\n };\n\n };\n\n this.$get = function() {\n var $tab = {};\n $tab.defaults = defaults;\n $tab.controller = controller;\n return $tab;\n };\n\n })\n\n .directive('bsTabs', function($window, $animate, $tab, $parse) {\n\n var defaults = $tab.defaults;\n\n return {\n require: ['?ngModel', 'bsTabs'],\n transclude: true,\n scope: true,\n controller: ['$scope', '$element', '$attrs', $tab.controller],\n templateUrl: function(element, attr) {\n return attr.template || defaults.template;\n },\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // 'ngModel' does interfere with form validation\n // and status, use `bsActivePane` instead to avoid it\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n bsTabsCtrl.$setActive(modelValue);\n return modelValue;\n });\n\n }\n\n if (attrs.bsActivePane) {\n // adapted from angularjs ngModelController bindings\n // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n // Update bsActivePane value with change\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n });\n\n // watch bsActivePane for value changes\n scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n bsTabsCtrl.$setActive(newValue);\n }, true);\n }\n }\n };\n\n })\n\n .directive('bsPane', function($window, $animate, $sce) {\n\n return {\n require: ['^?ngModel', '^bsTabs'],\n scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // Add base class\n element.addClass('tab-pane');\n\n // Observe title attribute for change\n attrs.$observe('title', function(newValue, oldValue) {\n scope.title = $sce.trustAsHtml(newValue);\n });\n\n // Save tab name into scope\n scope.name = attrs.name;\n\n // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\n }\n\n attrs.$observe('disabled', function(newValue, oldValue) {\n scope.disabled = scope.$eval(newValue);\n });\n\n // Push pane to parent bsTabs controller\n bsTabsCtrl.$push(scope);\n\n // remove pane from tab controller when pane is destroyed\n scope.$on('$destroy', function() {\n bsTabsCtrl.$remove(scope);\n });\n\n function render() {\n var index = bsTabsCtrl.$panes.indexOf(scope);\n $animate[bsTabsCtrl.$isActive(scope, index) ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.timepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$timepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'timepicker',\n prefixClass: 'timepicker',\n placement: 'bottom-left',\n template: 'timepicker/timepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: true,\n timeType: 'date',\n timeFormat: 'shortTime',\n timezone: null,\n modelTimeFormat: null,\n autoclose: false,\n minTime: -Infinity,\n maxTime: +Infinity,\n length: 5,\n hourStep: 1,\n minuteStep: 5,\n secondStep: 5,\n roundDisplay: false,\n iconUp: 'glyphicon glyphicon-chevron-up',\n iconDown: 'glyphicon glyphicon-chevron-down',\n arrowBehavior: 'pager'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function timepickerFactory(element, controller, config) {\n\n var $timepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $timepicker.$options;\n var scope = $timepicker.$scope;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n function floorMinutes(time)\n {\n // coeff used to floor current time to nearest minuteStep interval\n var coeff = 1000 * 60 * options.minuteStep;\n return new Date(Math.floor(time.getTime() / coeff) * coeff);\n }\n\n // View vars\n\n var selectedIndex = 0;\n var defaultDate = options.roundDisplay ? floorMinutes(new Date()) : new Date();\n var startDate = controller.$dateValue || defaultDate;\n var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n var hoursFormat = $dateFormatter.hoursFormat(format),\n timeSeparator = $dateFormatter.timeSeparator(format),\n minutesFormat = $dateFormatter.minutesFormat(format),\n secondsFormat = $dateFormatter.secondsFormat(format),\n showSeconds = $dateFormatter.showSeconds(format),\n showAM = $dateFormatter.showAM(format);\n\n scope.$iconUp = options.iconUp;\n scope.$iconDown = options.iconDown;\n\n // Scope methods\n\n scope.$select = function(date, index) {\n $timepicker.select(date, index);\n };\n scope.$moveIndex = function(value, index) {\n $timepicker.$moveIndex(value, index);\n };\n scope.$switchMeridian = function(date) {\n $timepicker.switchMeridian(date);\n };\n\n // Public methods\n\n $timepicker.update = function(date) {\n // console.warn('$timepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $timepicker.$date = date;\n angular.extend(viewDate, {hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds(), millisecond: date.getMilliseconds()});\n $timepicker.$build();\n } else if(!$timepicker.$isBuilt) {\n $timepicker.$build();\n }\n };\n\n $timepicker.select = function(date, index, keep) {\n // console.warn('$timepicker.select', date, scope.$mode);\n if(!controller.$dateValue || isNaN(controller.$dateValue.getTime())) controller.$dateValue = new Date(1970, 0, 1);\n if(!angular.isDate(date)) date = new Date(date);\n if(index === 0) controller.$dateValue.setHours(date.getHours());\n else if(index === 1) controller.$dateValue.setMinutes(date.getMinutes());\n else if(index === 2) controller.$dateValue.setSeconds(date.getSeconds());\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $timepicker.hide(true); });\n }\n };\n\n $timepicker.switchMeridian = function(date) {\n if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) {\n return;\n }\n var hours = (date || controller.$dateValue).getHours();\n controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12);\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n };\n\n // Protected methods\n\n $timepicker.$build = function() {\n // console.warn('$timepicker.$build() viewDate=%o', viewDate);\n var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n var hours = [], hour;\n for(i = 0; i < options.length; i++) {\n hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);\n hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});\n }\n var minutes = [], minute;\n for(i = 0; i < options.length; i++) {\n minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);\n minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n }\n var seconds = [], second;\n for(i = 0; i < options.length; i++) {\n second = new Date(1970, 0, 1, 0, 0, viewDate.second - (midIndex - i) * options.secondStep);\n seconds.push({date: second, label: formatDate(second, secondsFormat), selected: $timepicker.$date && $timepicker.$isSelected(second, 2), disabled: $timepicker.$isDisabled(second, 2)});\n }\n\n var rows = [];\n for(i = 0; i < options.length; i++) {\n if (showSeconds) {\n rows.push([hours[i], minutes[i], seconds[i]]);\n } else {\n rows.push([hours[i], minutes[i]]);\n }\n }\n scope.rows = rows;\n scope.showSeconds = showSeconds;\n scope.showAM = showAM;\n scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n scope.timeSeparator = timeSeparator;\n $timepicker.$isBuilt = true;\n };\n\n $timepicker.$isSelected = function(date, index) {\n if(!$timepicker.$date) return false;\n else if(index === 0) {\n return date.getHours() === $timepicker.$date.getHours();\n } else if(index === 1) {\n return date.getMinutes() === $timepicker.$date.getMinutes();\n } else if(index === 2) {\n return date.getSeconds() === $timepicker.$date.getSeconds();\n }\n };\n\n $timepicker.$isDisabled = function(date, index) {\n var selectedTime;\n if(index === 0) {\n selectedTime = date.getTime() + viewDate.minute * 6e4 + viewDate.second * 1e3;\n } else if(index === 1) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.second * 1e3;\n } else if(index === 2) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.minute * 6e4;\n }\n return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1;\n };\n\n scope.$arrowAction = function (value, index) {\n if (options.arrowBehavior === 'picker') {\n $timepicker.$setTimeByStep(value,index);\n } else {\n $timepicker.$moveIndex(value,index);\n }\n };\n\n $timepicker.$setTimeByStep = function(value, index) {\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n if (index === 0) {\n newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n }\n else if (index === 1) {\n newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\n }\n else if (index === 2) {\n newDate.setSeconds(seconds - (parseInt(options.secondStep, 10) * value));\n }\n $timepicker.select(newDate, index, true);\n };\n\n $timepicker.$moveIndex = function(value, index) {\n var targetDate;\n if(index === 0) {\n targetDate = new Date(1970, 0, 1, viewDate.hour + (value * options.length), viewDate.minute, viewDate.second);\n angular.extend(viewDate, {hour: targetDate.getHours()});\n } else if(index === 1) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + (value * options.length * options.minuteStep), viewDate.second);\n angular.extend(viewDate, {minute: targetDate.getMinutes()});\n } else if(index === 2) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute, viewDate.second + (value * options.length * options.secondStep));\n angular.extend(viewDate, {second: targetDate.getSeconds()});\n }\n $timepicker.$build();\n };\n\n $timepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n if(evt.target.nodeName.toLowerCase() !== 'input') evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $timepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Close on enter\n if(evt.keyCode === 13) return $timepicker.hide(true);\n\n // Navigate with keyboard\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n var sepLength = 1;\n var lateralMove = /(37|39)/.test(evt.keyCode);\n var count = 2 + showSeconds * 1 + showAM * 1;\n\n // Navigate indexes (left, right)\n if (lateralMove) {\n if(evt.keyCode === 37) selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1;\n else if(evt.keyCode === 39) selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0;\n }\n\n // Update values (up, down)\n var selectRange = [0, hoursLength];\n var incr = 0;\n if (evt.keyCode === 38) incr = -1;\n if (evt.keyCode === 40) incr = +1;\n var isSeconds = selectedIndex === 2 && showSeconds;\n var isMeridian = selectedIndex === 2 && !showSeconds || selectedIndex === 3 && showSeconds;\n if(selectedIndex === 0) {\n newDate.setHours(hours + incr*parseInt(options.hourStep, 10));\n // re-calculate hours length because we have changed hours value\n hoursLength = formatDate(newDate, hoursFormat).length;\n selectRange = [0, hoursLength];\n } else if(selectedIndex === 1) {\n newDate.setMinutes(minutes + incr*parseInt(options.minuteStep, 10));\n // re-calculate minutes length because we have changes minutes value\n minutesLength = formatDate(newDate, minutesFormat).length;\n selectRange = [hoursLength + sepLength, minutesLength];\n } else if(isSeconds) {\n newDate.setSeconds(seconds + incr*parseInt(options.secondStep, 10));\n // re-calculate seconds length because we have changes seconds value\n secondsLength = formatDate(newDate, secondsFormat).length;\n selectRange = [hoursLength + sepLength + minutesLength + sepLength, secondsLength];\n } else if(isMeridian) {\n if(!lateralMove) $timepicker.switchMeridian();\n selectRange = [hoursLength + sepLength + minutesLength + sepLength + (secondsLength + sepLength)*showSeconds, 2];\n }\n $timepicker.select(newDate, selectedIndex, true);\n createSelection(selectRange[0], selectRange[1]);\n parentScope.$digest();\n };\n\n // Private\n\n function createSelection(start, length) {\n var end = start + length;\n if(element[0].createTextRange) {\n var selRange = element[0].createTextRange();\n selRange.collapse(true);\n selRange.moveStart('character', start);\n selRange.moveEnd('character', end);\n selRange.select();\n } else if(element[0].setSelectionRange) {\n element[0].setSelectionRange(start, end);\n } else if(angular.isUndefined(element[0].selectionStart)) {\n element[0].selectionStart = start;\n element[0].selectionEnd = end;\n }\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $timepicker.init;\n $timepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'time');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $timepicker.destroy;\n $timepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $timepicker.show;\n $timepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $timepicker.$element && $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element && element.on('keydown', $timepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $timepicker.hide;\n $timepicker.hide = function(blur) {\n if(!$timepicker.$isShown) return;\n $timepicker.$element && $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element && element.off('keydown', $timepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $timepicker;\n\n }\n\n timepickerFactory.defaults = defaults;\n return timepickerFactory;\n\n };\n\n })\n\n\n .directive('bsTimepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n var defaults = $timepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'timeType', 'timeFormat', 'timezone', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'secondStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'roundDisplay', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative', 'roundDisplay'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!timepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(timepicker),?/i);\n newValue === true ? timepicker.show() : timepicker.hide();\n });\n\n // Initialize timepicker\n if(isNative && (options.useNative || defaults.useNative)) options.timeFormat = 'HH:mm';\n var timepicker = $timepicker(element, controller, options);\n options = timepicker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n // Initialize parser\n var dateParser = $dateParser({format: options.timeFormat, lang: lang});\n\n // Observe attributes for changes\n angular.forEach(['minTime', 'maxTime'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n !isNaN(timepicker.$options[key]) && timepicker.$build();\n validateAgainstMinMaxTime(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue);\n timepicker.update(controller.$dateValue);\n }, true);\n\n function validateAgainstMinMaxTime(parsedTime) {\n if (!angular.isDate(parsedTime)) return;\n var isMinValid = isNaN(options.minTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) >= options.minTime;\n var isMaxValid = isNaN(options.maxTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) <= options.maxTime;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(!isValid) {\n return;\n }\n controller.$dateValue = parsedTime;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n controller.$setValidity('date', true);\n return null;\n }\n var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedTime || isNaN(parsedTime.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxTime(parsedTime);\n }\n\n if(options.timeType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedTime, options.timezone, true);\n return formatDate(date, options.modelTimeFormat || options.timeFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.timeType === 'number') {\n return date.getTime();\n } else if(options.timeType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.timeType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.timeType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelTimeFormat);\n } else if(options.timeType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5);\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getTimeFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getTimeFormattedString());\n };\n\n function getTimeFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (timepicker) timepicker.destroy();\n options = null;\n timepicker = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$tooltip', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n prefixClass: 'tooltip',\n prefixEvent: 'tooltip',\n container: false,\n target: false,\n placement: 'top',\n template: 'tooltip/tooltip.tpl.html',\n contentTemplate: false,\n trigger: 'hover focus',\n keyboard: false,\n html: false,\n show: false,\n title: '',\n type: '',\n delay: 0,\n autoClose: false,\n bsEnabled: true,\n viewport: {\n selector: 'body',\n padding: 0\n }\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n var trim = String.prototype.trim;\n var isTouch = 'createTouch' in $window.document;\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n var $body = angular.element($window.document);\n\n function TooltipFactory(element, config) {\n\n var $tooltip = {};\n\n // Common vars\n var nodeName = element[0].nodeName.toLowerCase();\n var options = $tooltip.$options = angular.extend({}, defaults, config);\n $tooltip.$promise = fetchTemplate(options.template);\n var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(options.delay && angular.isString(options.delay)) {\n var split = options.delay.split(',').map(parseFloat);\n options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $tooltip.$id = options.id || element.attr('id') || '';\n\n // Support scope as string options\n if(options.title) {\n scope.title = $sce.trustAsHtml(options.title);\n }\n\n // Provide scope helpers\n scope.$setEnabled = function(isEnabled) {\n scope.$$postDigest(function() {\n $tooltip.setEnabled(isEnabled);\n });\n };\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $tooltip.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $tooltip.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $tooltip.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $tooltip.$isShown = scope.$isShown = false;\n\n // Private vars\n var timeout, hoverState;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $tooltip.$promise = $tooltip.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]);\n if(!contentEl.length) contentEl = findElement('[ng-bind=\"title\"]', templateEl[0]);\n contentEl.removeAttr('ng-bind').html(contentTemplate);\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize tooltip\n var tipLinker, tipElement, tipTemplate, tipContainer, tipScope;\n $tooltip.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n tipTemplate = template;\n tipLinker = $compile(template);\n $tooltip.init();\n });\n\n $tooltip.init = function() {\n\n // Options: delay\n if (options.delay && angular.isNumber(options.delay)) {\n options.delay = {\n show: options.delay,\n hide: options.delay\n };\n }\n\n // Replace trigger on touch devices ?\n // if(isTouch && options.trigger === defaults.trigger) {\n // options.trigger.replace(/hover/g, 'click');\n // }\n\n // Options : container\n if(options.container === 'self') {\n tipContainer = element;\n } else if(angular.isElement(options.container)) {\n tipContainer = options.container;\n } else if(options.container) {\n tipContainer = findElement(options.container);\n }\n\n // Options: trigger\n bindTriggerEvents();\n\n // Options: target\n if(options.target) {\n options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n }\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n options.trigger === 'focus' ? element[0].focus() : $tooltip.show();\n });\n }\n\n };\n\n $tooltip.destroy = function() {\n\n // Unbind events\n unbindTriggerEvents();\n\n // Remove element\n destroyTipElement();\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $tooltip.enter = function() {\n\n clearTimeout(timeout);\n hoverState = 'in';\n if (!options.delay || !options.delay.show) {\n return $tooltip.show();\n }\n\n timeout = setTimeout(function() {\n if (hoverState ==='in') $tooltip.show();\n }, options.delay.show);\n\n };\n\n $tooltip.show = function() {\n if (!options.bsEnabled || $tooltip.$isShown) return;\n\n scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n var parent, after;\n if (options.container) {\n parent = tipContainer;\n if (tipContainer[0].lastChild) {\n after = angular.element(tipContainer[0].lastChild);\n } else {\n after = null;\n }\n } else {\n parent = null;\n after = element;\n }\n\n\n // Hide any existing tipElement\n if(tipElement) destroyTipElement();\n // Fetch a cloned element linked from template\n tipScope = $tooltip.$scope.$new();\n tipElement = $tooltip.$element = tipLinker(tipScope, function(clonedElement, scope) {});\n\n // Set the initial positioning. Make the tooltip invisible\n // so IE doesn't try to focus on it off screen.\n tipElement.css({top: '-9999px', left: '-9999px', right: 'auto', display: 'block', visibility: 'hidden'});\n\n // Options: animation\n if(options.animation) tipElement.addClass(options.animation);\n // Options: type\n if(options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n // Options: custom classes\n if(options.customClass) tipElement.addClass(options.customClass);\n\n // Append the element, without any animations. If we append\n // using $animate.enter, some of the animations cause the placement\n // to be off due to the transforms.\n after ? after.after(tipElement) : parent.prepend(tipElement);\n\n $tooltip.$isShown = scope.$isShown = true;\n safeDigest(scope);\n\n // Now, apply placement\n $tooltip.$applyPlacement();\n\n // Once placed, animate it.\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if(angular.version.minor <= 2) {\n $animate.enter(tipElement, parent, after, enterAnimateCallback);\n } else {\n $animate.enter(tipElement, parent, after).then(enterAnimateCallback);\n }\n safeDigest(scope);\n\n $$rAF(function () {\n // Once the tooltip is placed and the animation starts, make the tooltip visible\n if(tipElement) tipElement.css({visibility: 'visible'});\n });\n\n // Bind events\n if(options.keyboard) {\n if(options.trigger !== 'focus') {\n $tooltip.focus();\n }\n bindKeyboardEvents();\n }\n\n if(options.autoClose) {\n bindAutoCloseEvents();\n }\n\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $tooltip);\n }\n\n $tooltip.leave = function() {\n\n clearTimeout(timeout);\n hoverState = 'out';\n if (!options.delay || !options.delay.hide) {\n return $tooltip.hide();\n }\n timeout = setTimeout(function () {\n if (hoverState === 'out') {\n $tooltip.hide();\n }\n }, options.delay.hide);\n\n };\n\n var _blur;\n var _tipToHide;\n $tooltip.hide = function(blur) {\n\n if(!$tooltip.$isShown) return;\n scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n\n // store blur value for leaveAnimateCallback to use\n _blur = blur;\n\n // store current tipElement reference to use\n // in leaveAnimateCallback\n _tipToHide = tipElement;\n\n // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if(angular.version.minor <= 2) {\n $animate.leave(tipElement, leaveAnimateCallback);\n } else {\n $animate.leave(tipElement).then(leaveAnimateCallback);\n }\n\n $tooltip.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.keyboard && tipElement !== null) {\n unbindKeyboardEvents();\n }\n\n if(options.autoClose && tipElement !== null) {\n unbindAutoCloseEvents();\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\n\n // check if current tipElement still references\n // the same element when hide was called\n if (tipElement === _tipToHide) {\n // Allow to blur the input when hidden, like when pressing enter key\n if(_blur && options.trigger === 'focus') {\n return element[0].blur();\n }\n\n // clean up child scopes\n destroyTipElement();\n }\n }\n\n $tooltip.toggle = function() {\n $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter();\n };\n\n $tooltip.focus = function() {\n tipElement[0].focus();\n };\n\n $tooltip.setEnabled = function(isEnabled) {\n options.bsEnabled = isEnabled;\n };\n\n $tooltip.setViewport = function(viewport) {\n options.viewport = viewport;\n };\n\n // Protected methods\n\n $tooltip.$applyPlacement = function() {\n if(!tipElement) return;\n\n // Determine if we're doing an auto or normal placement\n var placement = options.placement,\n autoToken = /\\s?auto?\\s?/i,\n autoPlace = autoToken.test(placement);\n\n if (autoPlace) {\n placement = placement.replace(autoToken, '') || defaults.placement;\n }\n\n // Need to add the position class before we get\n // the offsets\n tipElement.addClass(options.placement);\n\n // Get the position of the target element\n // and the height and width of the tooltip so we can center it.\n var elementPosition = getPosition(),\n tipWidth = tipElement.prop('offsetWidth'),\n tipHeight = tipElement.prop('offsetHeight');\n\n // If we're auto placing, we need to check the positioning\n if (autoPlace) {\n var originalPlacement = placement;\n var container = options.container ? findElement(options.container) : element.parent();\n var containerPosition = getPosition(container);\n\n // Determine if the vertical placement\n if (originalPlacement.indexOf('bottom') >= 0 && elementPosition.bottom + tipHeight > containerPosition.bottom) {\n placement = originalPlacement.replace('bottom', 'top');\n } else if (originalPlacement.indexOf('top') >= 0 && elementPosition.top - tipHeight < containerPosition.top) {\n placement = originalPlacement.replace('top', 'bottom');\n }\n\n // Determine the horizontal placement\n // The exotic placements of left and right are opposite of the standard placements. Their arrows are put on the left/right\n // and flow in the opposite direction of their placement.\n if ((originalPlacement === 'right' || originalPlacement === 'bottom-left' || originalPlacement === 'top-left') &&\n elementPosition.right + tipWidth > containerPosition.width) {\n\n placement = originalPlacement === 'right' ? 'left' : placement.replace('left', 'right');\n } else if ((originalPlacement === 'left' || originalPlacement === 'bottom-right' || originalPlacement === 'top-right') &&\n elementPosition.left - tipWidth < containerPosition.left) {\n\n placement = originalPlacement === 'left' ? 'right' : placement.replace('right', 'left');\n }\n\n tipElement.removeClass(originalPlacement).addClass(placement);\n }\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n applyPlacement(tipPosition, placement);\n };\n\n $tooltip.$onKeyUp = function(evt) {\n if (evt.which === 27 && $tooltip.$isShown) {\n $tooltip.hide();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusKeyUp = function(evt) {\n if (evt.which === 27) {\n element[0].blur();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusElementMouseDown = function(evt) {\n evt.preventDefault();\n evt.stopPropagation();\n // Some browsers do not auto-focus buttons (eg. Safari)\n $tooltip.$isShown ? element[0].blur() : element[0].focus();\n };\n\n // bind/unbind events\n function bindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n angular.forEach(triggers, function(trigger) {\n if(trigger === 'click') {\n element.on('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n });\n }\n\n function unbindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n for (var i = triggers.length; i--;) {\n var trigger = triggers[i];\n if(trigger === 'click') {\n element.off('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n }\n }\n\n function bindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.on('keyup', $tooltip.$onKeyUp);\n } else {\n element.on('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n function unbindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.off('keyup', $tooltip.$onKeyUp);\n } else {\n element.off('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n var _autoCloseEventsBinded = false;\n function bindAutoCloseEvents() {\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // Stop propagation when clicking inside tooltip\n tipElement.on('click', stopEventPropagation);\n\n // Hide when clicking outside tooltip\n $body.on('click', $tooltip.hide);\n\n _autoCloseEventsBinded = true;\n }, 0, false);\n }\n\n function unbindAutoCloseEvents() {\n if (_autoCloseEventsBinded) {\n tipElement.off('click', stopEventPropagation);\n $body.off('click', $tooltip.hide);\n _autoCloseEventsBinded = false;\n }\n }\n\n function stopEventPropagation(event) {\n event.stopPropagation();\n }\n\n // Private methods\n\n function getPosition($element) {\n $element = $element || (options.target || element);\n\n var el = $element[0],\n isBody = el.tagName === 'BODY';\n\n var elRect = el.getBoundingClientRect();\n var rect = {};\n\n // IE8 has issues with angular.extend and using elRect directly.\n // By coping the values of elRect into a new object, we can continue to use extend\n for (var p in elRect) {\n // DO NOT use hasOwnProperty when inspecting the return of getBoundingClientRect.\n rect[p] = elRect[p];\n }\n\n if (rect.width === null) {\n // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n rect = angular.extend({}, rect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });\n }\n var elOffset = isBody ? { top: 0, left: 0 } : dimensions.offset(el),\n scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.prop('scrollTop') || 0 },\n outerDims = isBody ? { width: document.documentElement.clientWidth, height: $window.innerHeight } : null;\n\n return angular.extend({}, rect, scroll, outerDims, elOffset);\n }\n\n function getCalculatedOffset(placement, position, actualWidth, actualHeight) {\n var offset;\n var split = placement.split('-');\n\n switch (split[0]) {\n case 'right':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left + position.width\n };\n break;\n case 'bottom':\n offset = {\n top: position.top + position.height,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n case 'left':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left - actualWidth\n };\n break;\n default:\n offset = {\n top: position.top - actualHeight,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n }\n\n if(!split[1]) {\n return offset;\n }\n\n // Add support for corners @todo css\n if(split[0] === 'top' || split[0] === 'bottom') {\n switch (split[1]) {\n case 'left':\n offset.left = position.left;\n break;\n case 'right':\n offset.left = position.left + position.width - actualWidth;\n }\n } else if(split[0] === 'left' || split[0] === 'right') {\n switch (split[1]) {\n case 'top':\n offset.top = position.top - actualHeight;\n break;\n case 'bottom':\n offset.top = position.top + position.height;\n }\n }\n\n return offset;\n }\n\n function applyPlacement(offset, placement) {\n var tip = tipElement[0],\n width = tip.offsetWidth,\n height = tip.offsetHeight;\n\n // manually read margins because getBoundingClientRect includes difference\n var marginTop = parseInt(dimensions.css(tip, 'margin-top'), 10),\n marginLeft = parseInt(dimensions.css(tip, 'margin-left'), 10);\n\n // we must check for NaN for ie 8/9\n if (isNaN(marginTop)) marginTop = 0;\n if (isNaN(marginLeft)) marginLeft = 0;\n\n offset.top = offset.top + marginTop;\n offset.left = offset.left + marginLeft;\n\n // dimensions setOffset doesn't round pixel values\n // so we use setOffset directly with our own function\n dimensions.setOffset(tip, angular.extend({\n using: function (props) {\n tipElement.css({\n top: Math.round(props.top) + 'px',\n left: Math.round(props.left) + 'px',\n right: ''\n });\n }\n }, offset), 0);\n\n // check to see if placing tip in new offset caused the tip to resize itself\n var actualWidth = tip.offsetWidth,\n actualHeight = tip.offsetHeight;\n\n if (placement === 'top' && actualHeight !== height) {\n offset.top = offset.top + height - actualHeight;\n }\n\n // If it's an exotic placement, exit now instead of\n // applying a delta and changing the arrow\n if (/top-left|top-right|bottom-left|bottom-right/.test(placement)) return;\n\n var delta = getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);\n\n if (delta.left) {\n offset.left += delta.left;\n } else {\n offset.top += delta.top;\n }\n\n dimensions.setOffset(tip, offset);\n\n if (/top|right|bottom|left/.test(placement)) {\n var isVertical = /top|bottom/.test(placement),\n arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight,\n arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';\n\n replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical);\n }\n }\n\n function getViewportAdjustedDelta(placement, position, actualWidth, actualHeight) {\n var delta = { top: 0, left: 0 },\n $viewport = options.viewport && findElement(options.viewport.selector || options.viewport);\n\n if (!$viewport) {\n return delta;\n }\n\n var viewportPadding = options.viewport && options.viewport.padding || 0,\n viewportDimensions = getPosition($viewport);\n\n if (/right|left/.test(placement)) {\n var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll,\n bottomEdgeOffset = position.top + viewportPadding - viewportDimensions.scroll + actualHeight;\n if (topEdgeOffset < viewportDimensions.top) { // top overflow\n delta.top = viewportDimensions.top - topEdgeOffset;\n } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;\n }\n } else {\n var leftEdgeOffset = position.left - viewportPadding,\n rightEdgeOffset = position.left + viewportPadding + actualWidth;\n if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n delta.left = viewportDimensions.left - leftEdgeOffset;\n } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow\n delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;\n }\n }\n\n return delta;\n }\n\n function replaceArrow(delta, dimension, isHorizontal) {\n var $arrow = findElement('.tooltip-arrow, .arrow', tipElement[0]);\n\n $arrow.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')\n .css(isHorizontal ? 'top' : 'left', '');\n }\n\n function destroyTipElement() {\n // Cancel pending callbacks\n clearTimeout(timeout);\n\n if($tooltip.$isShown && tipElement !== null) {\n if(options.autoClose) {\n unbindAutoCloseEvents();\n }\n\n if(options.keyboard) {\n unbindKeyboardEvents();\n }\n }\n\n if(tipScope) {\n tipScope.$destroy();\n tipScope = null;\n }\n\n if(tipElement) {\n tipElement.remove();\n tipElement = $tooltip.$element = null;\n }\n }\n\n return $tooltip;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return TooltipFactory;\n\n };\n\n })\n\n .directive('bsTooltip', function($window, $location, $sce, $tooltip, $$rAF) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Observe scope attributes for change\n attr.$observe('title', function(newValue) {\n if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n var oldValue = scope.title;\n scope.title = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }\n });\n\n // Support scope as an object\n attr.bsTooltip && scope.$watch(attr.bsTooltip, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.title = newValue;\n }\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n newValue === true ? tooltip.show() : tooltip.hide();\n });\n\n // Enabled binding support\n attr.bsEnabled && scope.$watch(attr.bsEnabled, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n newValue === false ? tooltip.setEnabled(false) : tooltip.setEnabled(true);\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n tooltip.setViewport(newValue);\n });\n\n // Initialize popover\n var tooltip = $tooltip(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(tooltip) tooltip.destroy();\n options = null;\n tooltip = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$typeahead', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'typeahead',\n prefixEvent: '$typeahead',\n placement: 'bottom-left',\n template: 'typeahead/typeahead.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n minLength: 1,\n filter: 'filter',\n limit: 6,\n autoSelect: false,\n comparator: '',\n trimValue: true\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n\n function TypeaheadFactory(element, controller, config) {\n\n var $typeahead = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $typeahead = $tooltip(element, options);\n var parentScope = config.scope;\n var scope = $typeahead.$scope;\n\n scope.$resetMatches = function(){\n scope.$matches = [];\n scope.$activeIndex = options.autoSelect ? 0 : -1; // If set to 0, the first match will be highlighted\n };\n scope.$resetMatches();\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $typeahead.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $typeahead.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $typeahead.$isVisible();\n };\n\n // Public methods\n\n $typeahead.update = function(matches) {\n scope.$matches = matches;\n if(scope.$activeIndex >= matches.length) {\n scope.$activeIndex = options.autoSelect ? 0: -1;\n }\n\n // When the placement is not one of the bottom placements, re-calc the positioning\n // so the results render correctly.\n if (/^(bottom|bottom-left|bottom-right)$/.test(options.placement)) return;\n\n // wrap in a $timeout so the results are updated\n // before repositioning\n $timeout($typeahead.$applyPlacement);\n };\n\n $typeahead.activate = function(index) {\n scope.$activeIndex = index;\n };\n\n $typeahead.select = function(index) {\n if(index === -1) return;\n var value = scope.$matches[index].value;\n // console.log('$setViewValue', value);\n controller.$setViewValue(value);\n controller.$render();\n scope.$resetMatches();\n if(parentScope) parentScope.$digest();\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $typeahead);\n };\n\n // Protected methods\n\n $typeahead.$isVisible = function() {\n if(!options.minLength || !controller) {\n return !!scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength;\n };\n\n $typeahead.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $typeahead.$onMouseDown = function(evt) {\n // Prevent blur on mousedown\n evt.preventDefault();\n evt.stopPropagation();\n };\n\n $typeahead.$onKeyDown = function(evt) {\n if(!/(38|40|13)/.test(evt.keyCode)) return;\n\n // Let ngSubmit pass if the typeahead tip is hidden or no option is selected\n if($typeahead.$isVisible() && !(evt.keyCode === 13 && scope.$activeIndex === -1)) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n // Select with enter\n if(evt.keyCode === 13 && scope.$matches.length) {\n $typeahead.select(scope.$activeIndex);\n }\n\n // Navigate with keyboard\n else if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n };\n\n // Overrides\n\n var show = $typeahead.show;\n $typeahead.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed immediately.\n $timeout(function() {\n $typeahead.$element && $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element && element.on('keydown', $typeahead.$onKeyDown);\n }\n }, 0, false);\n };\n\n var hide = $typeahead.hide;\n $typeahead.hide = function() {\n $typeahead.$element && $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element && element.off('keydown', $typeahead.$onKeyDown);\n }\n if(!options.autoSelect)\n $typeahead.activate(-1);\n hide();\n };\n\n return $typeahead;\n\n }\n\n TypeaheadFactory.defaults = defaults;\n return TypeaheadFactory;\n\n };\n\n })\n\n .directive('bsTypeahead', function($window, $parse, $q, $typeahead, $parseOptions) {\n\n var defaults = $typeahead.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'filter', 'limit', 'minLength', 'watchOptions', 'selectMode', 'autoSelect', 'comparator', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'trimValue'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n });\n\n // Disable browser autocompletion\n element.attr('autocomplete' ,'off');\n\n // Build proper bsOptions\n var filter = options.filter || defaults.filter;\n var limit = options.limit || defaults.limit;\n var comparator = options.comparator || defaults.comparator;\n\n var bsOptions = attr.bsOptions;\n if(filter) bsOptions += ' | ' + filter + ':$viewValue';\n if (comparator) bsOptions += ':' + comparator;\n if(limit) bsOptions += ' | limitTo:' + limit;\n var parsedOptions = $parseOptions(bsOptions);\n\n // Initialize typeahead\n var typeahead = $typeahead(element, controller, options);\n\n // Watch options on demand\n if(options.watchOptions) {\n // Watch bsOptions values before filtering for changes, drop function calls\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n scope.$watchCollection(watchedOptions, function (newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller).then(function (values) {\n typeahead.update(values);\n controller.$render();\n });\n });\n }\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('$watch', element.attr('ng-model'), newValue);\n scope.$modelValue = newValue; // Publish modelValue on scope for custom templates\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n // Prevent input with no future prospect if selectMode is truthy\n // @TODO test selectMode\n if(options.selectMode && !values.length && newValue.length > 0) {\n controller.$setViewValue(controller.$viewValue.substring(0, controller.$viewValue.length - 1));\n return;\n }\n if(values.length > limit) values = values.slice(0, limit);\n var isVisible = typeahead.$isVisible();\n isVisible && typeahead.update(values);\n // Do not re-queue an update if a correct value has been selected\n if(values.length === 1 && values[0].value === newValue) return;\n !isVisible && typeahead.update(values);\n // Queue a new rendering that will leverage collection loading\n controller.$render();\n });\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var displayValue = parsedOptions.displayValue(modelValue);\n\n // If we can determine the displayValue, use that\n if (displayValue) return displayValue;\n\n // If there's no display value, attempt to use the modelValue.\n // If the model is an object not much we can do\n if (modelValue && typeof modelValue !== 'object') {\n return modelValue;\n }\n return '';\n });\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n if(controller.$isEmpty(controller.$viewValue)) return element.val('');\n var index = typeahead.$getIndex(controller.$modelValue);\n var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;\n selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;\n var value = selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '') : '';\n element.val(options.trimValue === false ? value : value.trim());\n };\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (typeahead) typeahead.destroy();\n options = null;\n typeahead = null;\n });\n\n }\n };\n\n });\n"],"sourceRoot":"/source/"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * angular-strap
3
- * @version v2.2.3 - 2015-05-20
3
+ * @version v2.2.4 - 2015-05-28
4
4
  * @link http://mgcrea.github.io/angular-strap
5
5
  * @author Olivier Louvignes <olivier@mg-crea.com> (https://github.com/mgcrea)
6
6
  * @license MIT License, http://www.opensource.org/licenses/MIT