diff --git a/bower.json b/bower.json
index 6ac21741c..d5ee28752 100644
--- a/bower.json
+++ b/bower.json
@@ -1,7 +1,7 @@
{
"name": "angular-strap",
"description": "AngularStrap - AngularJS directives for Bootstrap",
- "version": "2.1.3",
+ "version": "2.1.4",
"keywords": [
"angular",
"bootstrap"
diff --git a/dist/angular-strap.js b/dist/angular-strap.js
index 172cf64e4..68276ac25 100644
--- a/dist/angular-strap.js
+++ b/dist/angular-strap.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -74,33 +74,35 @@ angular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mg
$affix.init = function() {
- $affix.$parseOffsets();
+ this.$parseOffsets();
initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;
setWidth = !element[0].style.width;
// Bind events
- targetEl.on('scroll', $affix.checkPosition);
- targetEl.on('click', $affix.checkPositionWithEventLoop);
- windowEl.on('resize', $affix.$debouncedOnResize);
+ targetEl.on('scroll', this.checkPosition);
+ targetEl.on('click', this.checkPositionWithEventLoop);
+ windowEl.on('resize', this.$debouncedOnResize);
// Both of these checkPosition() calls are necessary for the case where
// the user hits refresh after scrolling to the bottom of the page.
- $affix.checkPosition();
- $affix.checkPositionWithEventLoop();
+ this.checkPosition();
+ this.checkPositionWithEventLoop();
};
$affix.destroy = function() {
// Unbind events
- targetEl.off('scroll', $affix.checkPosition);
- targetEl.off('click', $affix.checkPositionWithEventLoop);
- windowEl.off('resize', $affix.$debouncedOnResize);
+ targetEl.off('scroll', this.checkPosition);
+ targetEl.off('click', this.checkPositionWithEventLoop);
+ windowEl.off('resize', this.$debouncedOnResize);
};
$affix.checkPositionWithEventLoop = function() {
+ // IE 9 throws an error if we use 'this' instead of '$affix'
+ // in this setTimeout call
setTimeout($affix.checkPosition, 1);
};
@@ -793,7 +795,10 @@ angular.module('mgcrea.ngStrap.collapse', [])
}]);
// Source: datepicker.js
-angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser', 'mgcrea.ngStrap.tooltip'])
+angular.module('mgcrea.ngStrap.datepicker', [
+ 'mgcrea.ngStrap.helpers.dateParser',
+ 'mgcrea.ngStrap.helpers.dateFormatter',
+ 'mgcrea.ngStrap.tooltip'])
.provider('$datepicker', function() {
@@ -813,6 +818,10 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
dateFormat: 'shortDate',
modelDateFormat: null,
dayFormat: 'dd',
+ monthFormat: 'MMM',
+ yearFormat: 'yyyy',
+ monthTitleFormat: 'MMMM yyyy',
+ yearTitleFormat: 'yyyy',
strictFormat: false,
autoclose: false,
minDate: -Infinity,
@@ -825,12 +834,12 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
iconRight: 'glyphicon glyphicon-chevron-right'
};
- this.$get = ["$window", "$document", "$rootScope", "$sce", "$locale", "dateFilter", "datepickerViews", "$tooltip", "$timeout", function($window, $document, $rootScope, $sce, $locale, dateFilter, datepickerViews, $tooltip, $timeout) {
+ this.$get = ["$window", "$document", "$rootScope", "$sce", "$dateFormatter", "datepickerViews", "$tooltip", "$timeout", function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {
var bodyEl = angular.element($window.document.body);
var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
var isTouch = ('createTouch' in $window.document) && isNative;
- if(!defaults.lang) defaults.lang = $locale.id;
+ if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();
function DatepickerFactory(element, controller, config) {
@@ -929,7 +938,10 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
$datepicker.$selectPane = function(value) {
var steps = $picker.steps;
- var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), viewDate.date + ((steps.day || 0) * value)));
+ // set targetDate to first day of month to avoid problems with
+ // date values rollover. This assumes the viewDate does not
+ // depend on the day of the month
+ var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));
angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});
$datepicker.$build();
};
@@ -1003,10 +1015,14 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
var _show = $datepicker.show;
$datepicker.show = function() {
_show();
- $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);
- if(options.keyboard) {
- element.on('keydown', $datepicker.$onKeyDown);
- }
+ // use timeout to hookup the events to prevent
+ // event bubbling from being processed imediately.
+ $timeout(function() {
+ $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);
+ if(options.keyboard) {
+ element.on('keydown', $datepicker.$onKeyDown);
+ }
+ }, 0, false);
};
var _hide = $datepicker.hide;
@@ -1030,7 +1046,7 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
})
- .directive('bsDatepicker', ["$window", "$parse", "$q", "$locale", "dateFilter", "$datepicker", "$dateParser", function($window, $parse, $q, $locale, dateFilter, $datepicker, $dateParser) {
+ .directive('bsDatepicker', ["$window", "$parse", "$q", "$dateFormatter", "$dateParser", "$datepicker", function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {
var defaults = $datepicker.defaults;
var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
@@ -1059,8 +1075,13 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
// Set expected iOS format
if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';
- // Initialize parser
- var dateParser = $dateParser({format: options.dateFormat, lang: options.lang, strict: options.strictFormat});
+ var lang = options.lang;
+
+ var formatDate = function(date, format) {
+ return $dateFormatter.formatDate(date, format, lang);
+ };
+
+ var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});
// Observe attributes for changes
angular.forEach(['minDate', 'maxDate'], function(key) {
@@ -1115,17 +1136,22 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
// Null values should correctly reset the model value & validity
if(!viewValue) {
controller.$setValidity('date', true);
- return;
+ // BREAKING CHANGE:
+ // return null (not undefined) when input value is empty, so angularjs 1.3
+ // ngModelController can go ahead and run validators, like ngRequired
+ return null;
}
var parsedDate = dateParser.parse(viewValue, controller.$dateValue);
if(!parsedDate || isNaN(parsedDate.getTime())) {
controller.$setValidity('date', false);
+ // return undefined, causes ngModelController to
+ // invalidate model value
return;
} else {
validateAgainstMinMaxDate(parsedDate);
}
if(options.dateType === 'string') {
- return dateFilter(parsedDate, options.modelDateFormat || options.dateFormat);
+ return formatDate(parsedDate, options.modelDateFormat || options.dateFormat);
} else if(options.dateType === 'number') {
return controller.$dateValue.getTime();
} else if(options.dateType === 'iso') {
@@ -1154,15 +1180,19 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
// date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);
// }
controller.$dateValue = date;
- return controller.$dateValue;
+ return getDateFormattedString();
});
// viewValue -> element
controller.$render = function() {
// console.warn('$render("%s"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);
- element.val(!controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : dateFilter(controller.$dateValue, options.dateFormat));
+ element.val(getDateFormattedString());
};
+ function getDateFormattedString() {
+ return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);
+ }
+
// Garbage collection
scope.$on('$destroy', function() {
if(datepicker) datepicker.destroy();
@@ -1196,15 +1226,20 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
return ((n % m) + m) % m;
}
- this.$get = ["$locale", "$sce", "dateFilter", "$dateParser", function($locale, $sce, dateFilter, $dateParser) {
+ this.$get = ["$dateFormatter", "$dateParser", "$sce", function($dateFormatter, $dateParser, $sce) {
return function(picker) {
var scope = picker.$scope;
var options = picker.$options;
- var dateParser = $dateParser();
- var weekDaysMin = $locale.DATETIME_FORMATS.SHORTDAY;
+ var lang = options.lang;
+ var formatDate = function(date, format) {
+ return $dateFormatter.formatDate(date, format, lang);
+ };
+ var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});
+
+ var weekDaysMin = $dateFormatter.weekdaysShort(lang);
var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));
var weekDaysLabelsHtml = $sce.trustAsHtml('
' + weekDaysLabels.join(' ') + ' ');
@@ -1233,10 +1268,10 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);
var days = [], day;
for(var i = 0; i < 42; i++) { // < 7 * 6
- day = new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i);
- days.push({date: day, isToday: day.toDateString() === today, label: dateFilter(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});
+ day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));
+ 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)});
}
- scope.title = dateFilter(firstDayOfMonth, 'MMMM yyyy');
+ scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);
scope.showLabels = true;
scope.labels = weekDaysLabelsHtml;
scope.rows = split(days, this.split);
@@ -1281,7 +1316,7 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
}
}, {
name: 'month',
- format: 'MMM',
+ format: options.monthFormat,
split: 4,
steps: { year: 1 },
update: function(date, force) {
@@ -1298,9 +1333,9 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
var months = [], month;
for (var i = 0; i < 12; i++) {
month = new Date(viewDate.year, i, 1);
- months.push({date: month, label: dateFilter(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});
+ months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});
}
- scope.title = dateFilter(month, 'yyyy');
+ scope.title = formatDate(month, options.yearTitleFormat);
scope.showLabels = false;
scope.rows = split(months, this.split);
this.built = true;
@@ -1328,7 +1363,7 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
}
}, {
name: 'year',
- format: 'yyyy',
+ format: options.yearFormat,
split: 4,
steps: { year: 12 },
update: function(date, force) {
@@ -1345,7 +1380,7 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
var years = [], year;
for (var i = 0; i < 12; i++) {
year = new Date(firstYear + i, 0, 1);
- years.push({date: year, label: dateFilter(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});
+ years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});
}
scope.title = years[0].label + '-' + years[years.length - 1].label;
scope.showLabels = false;
@@ -1403,7 +1438,7 @@ angular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])
delay: 0
};
- this.$get = ["$window", "$rootScope", "$tooltip", function($window, $rootScope, $tooltip) {
+ this.$get = ["$window", "$rootScope", "$tooltip", "$timeout", function($window, $rootScope, $tooltip, $timeout) {
var bodyEl = angular.element($window.document.body);
var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;
@@ -1447,8 +1482,12 @@ angular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])
var show = $dropdown.show;
$dropdown.show = function() {
show();
- options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);
- bodyEl.on('click', onBodyClick);
+ // use timeout to hookup the events to prevent
+ // event bubbling from being processed imediately.
+ $timeout(function() {
+ options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);
+ bodyEl.on('click', onBodyClick);
+ }, 0, false);
parentEl.hasClass('dropdown') && parentEl.addClass('open');
};
@@ -1461,6 +1500,12 @@ angular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])
hide();
};
+ var destroy = $dropdown.destroy;
+ $dropdown.destroy = function() {
+ bodyEl.off('click', onBodyClick);
+ destroy();
+ };
+
// Private functions
function onBodyClick(evt) {
@@ -1518,6 +1563,60 @@ angular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])
}]);
+// Source: date-formatter.js
+angular.module('mgcrea.ngStrap.helpers.dateFormatter', [])
+
+ .service('$dateFormatter', ["$locale", "dateFilter", function($locale, dateFilter) {
+
+ // The unused `lang` arguments are on purpose. The default implementation does not
+ // use them and it always uses the locale loaded into the `$locale` service.
+ // Custom implementations might use it, thus allowing different directives to
+ // have different languages.
+
+ this.getDefaultLocale = function() {
+ return $locale.id;
+ };
+
+ // Format is either a data format name, e.g. "shortTime" or "fullDate", or a date format
+ // Return either the corresponding date format or the given date format.
+ this.getDatetimeFormat = function(format, lang) {
+ return $locale.DATETIME_FORMATS[format] || format;
+ };
+
+ this.weekdaysShort = function(lang) {
+ return $locale.DATETIME_FORMATS.SHORTDAY;
+ };
+
+ function splitTimeFormat(format) {
+ return /(h+)([:\.])?(m+)[ ]?(a?)/i.exec(format).slice(1);
+ }
+
+ // h:mm a => h
+ this.hoursFormat = function(timeFormat) {
+ return splitTimeFormat(timeFormat)[0];
+ };
+
+ // h:mm a => mm
+ this.minutesFormat = function(timeFormat) {
+ return splitTimeFormat(timeFormat)[2];
+ };
+
+ // h:mm a => :
+ this.timeSeparator = function(timeFormat) {
+ return splitTimeFormat(timeFormat)[1];
+ };
+
+ // h:mm a => true, H.mm => false
+ this.showAM = function(timeFormat) {
+ return !!splitTimeFormat(timeFormat)[3];
+ };
+
+ this.formatDate = function(date, format, lang){
+ return dateFilter(date, format);
+ };
+
+ }]);
+
// Source: date-parser.js
angular.module('mgcrea.ngStrap.helpers.dateParser', [])
@@ -1650,6 +1749,8 @@ angular.module('mgcrea.ngStrap.helpers.dateParser', [])
};
$dateParser.parse = function(value, baseDate, format) {
+ // check for date format special names
+ if(format) format = $locale.DATETIME_FORMATS[format] || format;
if(angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format);
var formatRegex = format ? regExpForFormat(format) : regex;
var formatSetMap = format ? setMapForFormat(format) : setMap;
@@ -1701,6 +1802,23 @@ angular.module('mgcrea.ngStrap.helpers.dateParser', [])
return time;
};
+ /* Handle switch to/from daylight saving.
+ * Hours may be non-zero on daylight saving cut-over:
+ * > 12 when midnight changeover, but then cannot generate
+ * midnight datetime, so jump to 1AM, otherwise reset.
+ * @param date (Date) the date to check
+ * @return (Date) the corrected date
+ *
+ * __ copied from jquery ui datepicker __
+ */
+ $dateParser.daylightSavingAdjust = function(date) {
+ if (!date) {
+ return null;
+ }
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
+ return date;
+ };
+
// Private functions
function setMapForFormat(format) {
@@ -2206,13 +2324,19 @@ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])
if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {
return;
}
- var parent;
+ var parent, after;
if(angular.isElement(options.container)) {
parent = options.container;
+ after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;
} else {
- parent = options.container ? findElement(options.container) : null;
+ if (options.container) {
+ parent = findElement(options.container);
+ after = parent[0].lastChild ? angular.element(parent[0].lastChild) : null;
+ } else {
+ parent = null;
+ after = options.element;
+ }
}
- var after = options.container ? null : options.element;
// Fetch a cloned element linked from template
modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});
@@ -2236,8 +2360,8 @@ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])
var promise = $animate.enter(modalElement, parent, after, enterAnimateCallback);
if(promise && promise.then) promise.then(enterAnimateCallback);
- scope.$isShown = true;
- scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
+ $modal.$isShown = scope.$isShown = true;
+ safeDigest(scope);
// Focus once the enter-animation has started
// Weird PhantomJS bug hack
var el = modalElement[0];
@@ -2278,8 +2402,8 @@ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])
if(options.backdrop) {
$animate.leave(backdropElement);
}
- scope.$isShown = false;
- scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
+ $modal.$isShown = scope.$isShown = false;
+ safeDigest(scope);
// Unbind events
if(options.backdrop) {
@@ -2333,19 +2457,25 @@ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])
// Helper functions
+ function safeDigest(scope) {
+ scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
+ }
+
function findElement(query, element) {
return angular.element((element || document).querySelectorAll(query));
}
+ var fetchPromises = {};
function fetchTemplate(template) {
- return $q.when($templateCache.get(template) || $http.get(template))
+ if(fetchPromises[template]) return fetchPromises[template];
+ return (fetchPromises[template] = $q.when($templateCache.get(template) || $http.get(template))
.then(function(res) {
if(angular.isObject(res)) {
$templateCache.put(template, res.data);
return res.data;
}
return res;
- });
+ }));
}
return ModalFactory;
@@ -2696,7 +2826,9 @@ angular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', '
};
$scrollspy.checkPositionWithEventLoop = function() {
- setTimeout(this.checkPosition, 1);
+ // IE 9 throws an error if we use 'this' instead of '$scrollspy'
+ // in this setTimeout call
+ setTimeout($scrollspy.checkPosition, 1);
};
// Protected methods
@@ -2849,7 +2981,7 @@ angular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStr
iconCheckmark: 'glyphicon glyphicon-ok'
};
- this.$get = ["$window", "$document", "$rootScope", "$tooltip", function($window, $document, $rootScope, $tooltip) {
+ this.$get = ["$window", "$document", "$rootScope", "$tooltip", "$timeout", function($window, $document, $rootScope, $tooltip, $timeout) {
var bodyEl = angular.element($window.document.body);
var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
@@ -3021,10 +3153,14 @@ angular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStr
if(options.multiple) {
$select.$element.addClass('select-multiple');
}
- $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);
- if(options.keyboard) {
- element.on('keydown', $select.$onKeyDown);
- }
+ // use timeout to hookup the events to prevent
+ // event bubbling from being processed imediately.
+ $timeout(function() {
+ $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);
+ if(options.keyboard) {
+ element.on('keydown', $select.$onKeyDown);
+ }
+ }, 0, false);
};
var _hide = $select.hide;
@@ -3115,6 +3251,12 @@ angular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStr
element.html((selected ? selected : options.placeholder) + defaults.caretHtml);
};
+ if(options.multiple){
+ controller.$isEmpty = function(value){
+ return !value || value.length === 0;
+ };
+ }
+
// Garbage collection
scope.$on('$destroy', function() {
if (select) select.destroy();
@@ -3154,7 +3296,10 @@ angular.module('mgcrea.ngStrap.tab', [])
self.$panes = $scope.$panes = [];
- self.$viewChangeListeners = [];
+ // DEPRECATED: $viewChangeListeners, please use $activePaneChangeListeners
+ // Because we deprecated ngModel usage, we rename viewChangeListeners to
+ // activePaneChangeListeners to make more sense.
+ self.$activePaneChangeListeners = self.$viewChangeListeners = [];
self.$push = function(pane) {
self.$panes.push(pane);
@@ -3183,7 +3328,7 @@ angular.module('mgcrea.ngStrap.tab', [])
self.$panes.$active = 0;
self.$setActive = $scope.$setActive = function(value) {
self.$panes.$active = value;
- self.$viewChangeListeners.forEach(function(fn) {
+ self.$activePaneChangeListeners.forEach(function(fn) {
fn();
});
};
@@ -3199,7 +3344,7 @@ angular.module('mgcrea.ngStrap.tab', [])
})
- .directive('bsTabs', ["$window", "$animate", "$tab", function($window, $animate, $tab) {
+ .directive('bsTabs', ["$window", "$animate", "$tab", "$parse", function($window, $animate, $tab, $parse) {
var defaults = $tab.defaults;
@@ -3216,10 +3361,14 @@ angular.module('mgcrea.ngStrap.tab', [])
var ngModelCtrl = controllers[0];
var bsTabsCtrl = controllers[1];
+ // DEPRECATED: ngModel, please use bsActivePane
+ // 'ngModel' is deprecated bacause if interferes with form validation
+ // and status, so avoid using it here.
if(ngModelCtrl) {
+ console.warn('Usage of ngModel is deprecated, please use bsActivePane instead!');
// Update the modelValue following
- bsTabsCtrl.$viewChangeListeners.push(function() {
+ bsTabsCtrl.$activePaneChangeListeners.push(function() {
ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);
});
@@ -3232,6 +3381,21 @@ angular.module('mgcrea.ngStrap.tab', [])
}
+ if (attrs.bsActivePane) {
+ // adapted from angularjs ngModelController bindings
+ // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730
+ var parsedBsActivePane = $parse(attrs.bsActivePane);
+
+ // Update bsActivePane value with change
+ bsTabsCtrl.$activePaneChangeListeners.push(function() {
+ parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);
+ });
+
+ // watch bsActivePane for value changes
+ scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {
+ bsTabsCtrl.$setActive(newValue * 1);
+ }, true);
+ }
}
};
@@ -3274,7 +3438,7 @@ angular.module('mgcrea.ngStrap.tab', [])
$animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);
}
- bsTabsCtrl.$viewChangeListeners.push(function() {
+ bsTabsCtrl.$activePaneChangeListeners.push(function() {
render();
});
render();
@@ -3285,7 +3449,10 @@ angular.module('mgcrea.ngStrap.tab', [])
}]);
// Source: timepicker.js
-angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser', 'mgcrea.ngStrap.tooltip'])
+angular.module('mgcrea.ngStrap.timepicker', [
+ 'mgcrea.ngStrap.helpers.dateParser',
+ 'mgcrea.ngStrap.helpers.dateFormatter',
+ 'mgcrea.ngStrap.tooltip'])
.provider('$timepicker', function() {
@@ -3315,12 +3482,12 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
arrowBehavior: 'pager'
};
- this.$get = ["$window", "$document", "$rootScope", "$sce", "$locale", "dateFilter", "$tooltip", "$timeout", function($window, $document, $rootScope, $sce, $locale, dateFilter, $tooltip, $timeout) {
+ this.$get = ["$window", "$document", "$rootScope", "$sce", "$dateFormatter", "$tooltip", "$timeout", function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {
var bodyEl = angular.element($window.document.body);
var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
var isTouch = ('createTouch' in $window.document) && isNative;
- if(!defaults.lang) defaults.lang = $locale.id;
+ if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();
function timepickerFactory(element, controller, config) {
@@ -3329,14 +3496,24 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
var options = $timepicker.$options;
var scope = $timepicker.$scope;
+ var lang = options.lang;
+ var formatDate = function(date, format) {
+ return $dateFormatter.formatDate(date, format, lang);
+ };
+
// View vars
var selectedIndex = 0;
var startDate = controller.$dateValue || new Date();
var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};
- var format = $locale.DATETIME_FORMATS[options.timeFormat] || options.timeFormat;
- var formats = /(h+)([:\.])?(m+)[ ]?(a?)/i.exec(format).slice(1);
+ var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);
+
+ var hoursFormat = $dateFormatter.hoursFormat(format),
+ timeSeparator = $dateFormatter.timeSeparator(format),
+ minutesFormat = $dateFormatter.minutesFormat(format),
+ showAM = $dateFormatter.showAM(format);
+
scope.$iconUp = options.iconUp;
scope.$iconDown = options.iconDown;
@@ -3396,12 +3573,12 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
var hours = [], hour;
for(i = 0; i < options.length; i++) {
hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);
- hours.push({date: hour, label: dateFilter(hour, formats[0]), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});
+ hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});
}
var minutes = [], minute;
for(i = 0; i < options.length; i++) {
minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);
- minutes.push({date: minute, label: dateFilter(minute, formats[2]), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});
+ minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});
}
var rows = [];
@@ -3409,9 +3586,9 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
rows.push([hours[i], minutes[i]]);
}
scope.rows = rows;
- scope.showAM = !!formats[3];
+ scope.showAM = showAM;
scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;
- scope.timeSeparator = formats[1];
+ scope.timeSeparator = timeSeparator;
$timepicker.$isBuilt = true;
};
@@ -3444,8 +3621,8 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
$timepicker.$setTimeByStep = function(value, index) {
var newDate = new Date($timepicker.$date);
- var hours = newDate.getHours(), hoursLength = dateFilter(newDate, 'h').length;
- var minutes = newDate.getMinutes(), minutesLength = dateFilter(newDate, 'mm').length;
+ var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;
+ var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;
if (index === 0) {
newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));
}
@@ -3491,10 +3668,10 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
// Navigate with keyboard
var newDate = new Date($timepicker.$date);
- var hours = newDate.getHours(), hoursLength = dateFilter(newDate, 'h').length;
- var minutes = newDate.getMinutes(), minutesLength = dateFilter(newDate, 'mm').length;
+ var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;
+ var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;
var lateralMove = /(37|39)/.test(evt.keyCode);
- var count = 2 + !!formats[3] * 1;
+ var count = 2 + showAM * 1;
// Navigate indexes (left, right)
if (lateralMove) {
@@ -3507,10 +3684,14 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
if(selectedIndex === 0) {
if(evt.keyCode === 38) newDate.setHours(hours - parseInt(options.hourStep, 10));
else if(evt.keyCode === 40) newDate.setHours(hours + parseInt(options.hourStep, 10));
+ // re-calculate hours length because we have changed hours value
+ hoursLength = formatDate(newDate, hoursFormat).length;
selectRange = [0, hoursLength];
} else if(selectedIndex === 1) {
if(evt.keyCode === 38) newDate.setMinutes(minutes - parseInt(options.minuteStep, 10));
else if(evt.keyCode === 40) newDate.setMinutes(minutes + parseInt(options.minuteStep, 10));
+ // re-calculate minutes length because we have changes minutes value
+ minutesLength = formatDate(newDate, minutesFormat).length;
selectRange = [hoursLength + 1, hoursLength + 1 + minutesLength];
} else if(selectedIndex === 2) {
if(!lateralMove) $timepicker.switchMeridian();
@@ -3569,10 +3750,14 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
var _show = $timepicker.show;
$timepicker.show = function() {
_show();
- $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);
- if(options.keyboard) {
- element.on('keydown', $timepicker.$onKeyDown);
- }
+ // use timeout to hookup the events to prevent
+ // event bubbling from being processed imediately.
+ $timeout(function() {
+ $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);
+ if(options.keyboard) {
+ element.on('keydown', $timepicker.$onKeyDown);
+ }
+ }, 0, false);
};
var _hide = $timepicker.hide;
@@ -3597,7 +3782,7 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
})
- .directive('bsTimepicker', ["$window", "$parse", "$q", "$locale", "dateFilter", "$timepicker", "$dateParser", function($window, $parse, $q, $locale, dateFilter, $timepicker, $dateParser) {
+ .directive('bsTimepicker', ["$window", "$parse", "$q", "$dateFormatter", "$dateParser", "$timepicker", function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {
var defaults = $timepicker.defaults;
var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
@@ -3626,8 +3811,13 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
var timepicker = $timepicker(element, controller, options);
options = timepicker.$options;
+ var lang = options.lang;
+ var formatDate = function(date, format) {
+ return $dateFormatter.formatDate(date, format, lang);
+ };
+
// Initialize parser
- var dateParser = $dateParser({format: options.timeFormat, lang: options.lang});
+ var dateParser = $dateParser({format: options.timeFormat, lang: lang});
// Observe attributes for changes
angular.forEach(['minTime', 'maxTime'], function(key) {
@@ -3665,18 +3855,23 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
// console.warn('$parser("%s"): viewValue=%o', element.attr('ng-model'), viewValue);
// Null values should correctly reset the model value & validity
if(!viewValue) {
+ // BREAKING CHANGE:
+ // return null (not undefined) when input value is empty, so angularjs 1.3
+ // ngModelController can go ahead and run validators, like ngRequired
controller.$setValidity('date', true);
- return;
+ return null;
}
var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);
if(!parsedTime || isNaN(parsedTime.getTime())) {
controller.$setValidity('date', false);
+ // return undefined, causes ngModelController to
+ // invalidate model value
return;
} else {
validateAgainstMinMaxTime(parsedTime);
}
if(options.timeType === 'string') {
- return dateFilter(parsedTime, options.modelTimeFormat || options.timeFormat);
+ return formatDate(parsedTime, options.modelTimeFormat || options.timeFormat);
} else if(options.timeType === 'number') {
return controller.$dateValue.getTime();
} else if(options.timeType === 'iso') {
@@ -3712,7 +3907,7 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
};
function getTimeFormattedString() {
- return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : dateFilter(controller.$dateValue, options.timeFormat);
+ return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);
}
// Garbage collection
@@ -3753,7 +3948,7 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
bsEnabled: true
};
- this.$get = ["$window", "$rootScope", "$compile", "$q", "$templateCache", "$http", "$animate", "dimensions", "$$rAF", "$timeout", function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, dimensions, $$rAF, $timeout) {
+ this.$get = ["$window", "$rootScope", "$compile", "$q", "$templateCache", "$http", "$animate", "$sce", "dimensions", "$$rAF", "$timeout", function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {
var trim = String.prototype.trim;
var isTouch = 'createTouch' in $window.document;
@@ -3776,7 +3971,7 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
// Support scope as string options
if(options.title) {
- $tooltip.$scope.title = options.title;
+ scope.title = $sce.trustAsHtml(options.title);
}
// Provide scope helpers
@@ -3855,16 +4050,7 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
}
// Options: trigger
- var triggers = options.trigger.split(' ');
- angular.forEach(triggers, function(trigger) {
- if(trigger === 'click') {
- element.on('click', $tooltip.toggle);
- } else if(trigger !== 'manual') {
- element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);
- element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);
- nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);
- }
- });
+ bindTriggerEvents();
// Options: target
if(options.target) {
@@ -3883,22 +4069,7 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
$tooltip.destroy = function() {
// Unbind events
- var triggers = options.trigger.split(' ');
- for (var i = triggers.length; i--;) {
- var trigger = triggers[i];
- if(trigger === 'click') {
- element.off('click', $tooltip.toggle);
- } else if(trigger !== 'manual') {
- element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);
- element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);
- nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);
- }
- }
-
- if(options.autoClose && $tooltip.$isShown && tipElement !== null) {
- $body.off('click');
- tipElement.off('click');
- }
+ unbindTriggerEvents();
// Remove element
destroyTipElement();
@@ -3926,8 +4097,19 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
if (!options.bsEnabled) return;
scope.$emit(options.prefixEvent + '.show.before', $tooltip);
- var parent = options.container ? tipContainer : null;
- var after = options.container ? null : element;
+ var parent, after;
+ if (options.container) {
+ parent = tipContainer;
+ if (tipContainer[0].lastChild) {
+ after = angular.element(tipContainer[0].lastChild);
+ } else {
+ after = null;
+ }
+ } else {
+ parent = null;
+ after = element;
+ }
+
// Hide any existing tipElement
if(tipElement) destroyTipElement();
@@ -3952,7 +4134,7 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
if(promise && promise.then) promise.then(enterAnimateCallback);
$tooltip.$isShown = scope.$isShown = true;
- scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
+ safeDigest(scope);
$$rAF(function () {
$tooltip.$applyPlacement();
@@ -3964,27 +4146,12 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
if(options.keyboard) {
if(options.trigger !== 'focus') {
$tooltip.focus();
- tipElement.on('keyup', $tooltip.$onKeyUp);
- } else {
- element.on('keyup', $tooltip.$onFocusKeyUp);
}
+ bindKeyboardEvents();
}
if(options.autoClose) {
- // Stop propagation when clicking inside tooltip
- tipElement.on('click', function(event) {
- event.stopPropagation();
- });
-
- // Hide when clicking outside tooltip
- // use $timeout to setup this event, otherwise the
- // click on the element to show the popover will bubble
- // to the body and cause the popover to immediatly hide
- $timeout(function() {
- $body.on('click', function() {
- $tooltip.hide();
- });
- }, 0, false);
+ bindAutoCloseEvents();
}
};
@@ -4023,18 +4190,16 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
if(promise && promise.then) promise.then(leaveAnimateCallback);
$tooltip.$isShown = scope.$isShown = false;
- scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
+ safeDigest(scope);
// Unbind events
if(options.keyboard && tipElement !== null) {
- tipElement.off('keyup', $tooltip.$onKeyUp);
+ unbindKeyboardEvents();
}
if(options.autoClose && tipElement !== null) {
- $body.off('click');
- tipElement.off('click');
+ unbindAutoCloseEvents();
}
-
};
function leaveAnimateCallback() {
@@ -4103,6 +4268,77 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
$tooltip.$isShown ? element[0].blur() : element[0].focus();
};
+ // bind/unbind events
+ function bindTriggerEvents() {
+ var triggers = options.trigger.split(' ');
+ angular.forEach(triggers, function(trigger) {
+ if(trigger === 'click') {
+ element.on('click', $tooltip.toggle);
+ } else if(trigger !== 'manual') {
+ element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);
+ element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);
+ nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);
+ }
+ });
+ }
+
+ function unbindTriggerEvents() {
+ var triggers = options.trigger.split(' ');
+ for (var i = triggers.length; i--;) {
+ var trigger = triggers[i];
+ if(trigger === 'click') {
+ element.off('click', $tooltip.toggle);
+ } else if(trigger !== 'manual') {
+ element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);
+ element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);
+ nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);
+ }
+ }
+ }
+
+ function bindKeyboardEvents() {
+ if(options.trigger !== 'focus') {
+ tipElement.on('keyup', $tooltip.$onKeyUp);
+ } else {
+ element.on('keyup', $tooltip.$onFocusKeyUp);
+ }
+ }
+
+ function unbindKeyboardEvents() {
+ if(options.trigger !== 'focus') {
+ tipElement.off('keyup', $tooltip.$onKeyUp);
+ } else {
+ element.off('keyup', $tooltip.$onFocusKeyUp);
+ }
+ }
+
+ var _autoCloseEventsBinded = false;
+ function bindAutoCloseEvents() {
+ // use timeout to hookup the events to prevent
+ // event bubbling from being processed imediately.
+ $timeout(function() {
+ // Stop propagation when clicking inside tooltip
+ tipElement.on('click', stopEventPropagation);
+
+ // Hide when clicking outside tooltip
+ $body.on('click', $tooltip.hide);
+
+ _autoCloseEventsBinded = true;
+ }, 0, false);
+ }
+
+ function unbindAutoCloseEvents() {
+ if (_autoCloseEventsBinded) {
+ tipElement.off('click', stopEventPropagation);
+ $body.off('click', $tooltip.hide);
+ _autoCloseEventsBinded = false;
+ }
+ }
+
+ function stopEventPropagation(event) {
+ event.stopPropagation();
+ }
+
// Private methods
function getPosition() {
@@ -4174,12 +4410,22 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
// Cancel pending callbacks
clearTimeout(timeout);
- if (tipScope) {
+ if($tooltip.$isShown && tipElement !== null) {
+ if(options.autoClose) {
+ unbindAutoCloseEvents();
+ }
+
+ if(options.keyboard) {
+ unbindKeyboardEvents();
+ }
+ }
+
+ if(tipScope) {
tipScope.$destroy();
tipScope = null;
}
- if (tipElement) {
+ if(tipElement) {
tipElement.remove();
tipElement = $tooltip.$element = null;
}
@@ -4191,19 +4437,25 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
// Helper functions
+ function safeDigest(scope) {
+ scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
+ }
+
function findElement(query, element) {
return angular.element((element || document).querySelectorAll(query));
}
+ var fetchPromises = {};
function fetchTemplate(template) {
- return $q.when($templateCache.get(template) || $http.get(template))
+ if(fetchPromises[template]) return fetchPromises[template];
+ return (fetchPromises[template] = $q.when($templateCache.get(template) || $http.get(template))
.then(function(res) {
if(angular.isObject(res)) {
$templateCache.put(template, res.data);
return res.data;
}
return res;
- });
+ }));
}
return TooltipFactory;
@@ -4306,7 +4558,7 @@ angular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ng
comparator: ''
};
- this.$get = ["$window", "$rootScope", "$tooltip", function($window, $rootScope, $tooltip) {
+ this.$get = ["$window", "$rootScope", "$tooltip", "$timeout", function($window, $rootScope, $tooltip, $timeout) {
var bodyEl = angular.element($window.document.body);
@@ -4419,10 +4671,14 @@ angular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ng
var show = $typeahead.show;
$typeahead.show = function() {
show();
- $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);
- if(options.keyboard) {
- element.on('keydown', $typeahead.$onKeyDown);
- }
+ // use timeout to hookup the events to prevent
+ // event bubbling from being processed imediately.
+ $timeout(function() {
+ $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);
+ if(options.keyboard) {
+ element.on('keydown', $typeahead.$onKeyDown);
+ }
+ }, 0, false);
};
var hide = $typeahead.hide;
@@ -4523,7 +4779,7 @@ angular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ng
if(controller.$isEmpty(controller.$viewValue)) return element.val('');
var index = typeahead.$getIndex(controller.$modelValue);
var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;
- selected = angular.isObject(selected) ? selected.label : selected;
+ selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;
element.val(selected ? selected.toString().replace(/<(?:.|\n)*?>/gm, '').trim() : '');
};
diff --git a/dist/angular-strap.min.js b/dist/angular-strap.min.js
index ee5639694..f87034929 100644
--- a/dist/angular-strap.min.js
+++ b/dist/angular-strap.min.js
@@ -1,11 +1,11 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-!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"};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!==y&&t.top+n+$>=o-y?"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,y=0,w=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(){d.$parseOffsets(),h=a.offset(o[0]).top+$,m=!o[0].style.width,p.on("scroll",d.checkPosition),p.on("click",d.checkPositionWithEventLoop),r.on("resize",d.$debouncedOnResize),d.checkPosition(),d.checkPositionWithEventLoop()},d.destroy=function(){p.off("scroll",d.checkPosition),p.off("click",d.checkPositionWithEventLoop),r.off("resize",d.$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);w!==r&&(w=r,o.removeClass(g).addClass("affix"+("middle"!==r?"-"+r:"")),"top"===r?(b=null,o.css("position",f.offsetParent?"":"relative"),m&&o.css("width",""),o.css("top","")):"bottom"===r?(b=f.offsetUnpin?-(1*f.offsetUnpin):t.top-e,m&&o.css("width",""),o.css("position",f.offsetParent?"":"relative"),o.css("top",f.offsetParent?"":i[0].offsetHeight-y-n-h+"px")):(b=null,m&&o.css("width",o[0].offsetWidth+"px"),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");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&&(y=f.offsetParent&&f.offsetBottom.match(/^[-+]\d+$/)?c()-(a.offset(D[0]).top+a.height(D[0]))+1*f.offsetBottom+1:1*f.offsetBottom),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,offsetTop:"auto",target:i?i.$element:angular.element(t)};angular.forEach(["offsetTop","offsetBottom","offsetParent","offsetUnpin"],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});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){var i={scope:e,element:a,show:!1};angular.forEach(["template","placement","keyboard","html","container","animation","duration","dismissable"],function(e){angular.isDefined(o[e])&&(i[e]=o[e])}),angular.forEach(["title","content","type"],function(n){o[n]&&o.$observe(n,function(a){e[n]=t.trustAsHtml(a)})}),o.bsAlert&&e.$watch(o.bsAlert,function(t){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var r=n(i);a.on(o.trigger||"click",r.toggle),e.$on("$destroy",function(){r&&r.destroy(),i=null,r=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){var i={scope:e,element:a,show:!1};angular.forEach(["template","contentTemplate","placement","backdrop","keyboard","html","container","animation"],function(e){angular.isDefined(o[e])&&(i[e]=o[e])}),angular.forEach(["title","content"],function(n){o[n]&&o.$observe(n,function(a){e[n]=t.trustAsHtml(a)})}),o.bsAside&&e.$watch(o.bsAside,function(t){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var r=n(i);a.on(o.trigger||"click",r.toggle),e.$on("$destroy",function(){r&&r.destroy(),i=null,r=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(){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=n,l="INPUT"===o[0].nodeName,u=l?o.parent():o,c=a.test(i.value)?e.$eval(i.value):i.value;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(){r.$setViewValue(c),r.$render()})})}}}]),angular.module("mgcrea.ngStrap.collapse",[]).provider("$collapse",function(){var e=this.defaults={animation:"am-collapse",disallowToggle:!1,activeClass:"in",startCollapsed:!1},t=this.controller=function(t,n,a){var o=this;o.$options=angular.copy(e),angular.forEach(["animation","disallowToggle","activeClass","startCollapsed"],function(e){angular.isDefined(a[e])&&(o.$options[e]=a[e])}),o.$toggles=[],o.$targets=[],o.$viewChangeListeners=[],o.$registerToggle=function(e){o.$toggles.push(e)},o.$registerTarget=function(e){o.$targets.push(e)},o.$targets.$active=o.$options.startCollapsed?-1:0,o.$setActive=t.$setActive=function(e){o.$targets.$active=o.$options.disallowToggle?e:o.$targets.$active===e?-1:e,o.$viewChangeListeners.forEach(function(e){e()})}};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.$targets.$active)}),o.$formatters.push(function(e){return i.$targets.$active!==1*e&&i.$setActive(1*e),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),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.$targets.$active;e[t===a?"addClass":"removeClass"](n,r.$options.activeClass)}var r=(o[0],o[1]);n.addClass("collapse"),r.$options.animation&&n.addClass(r.$options.animation),r.$registerTarget(n),r.$viewChangeListeners.push(function(){i()}),i()}}}]),angular.module("mgcrea.ngStrap.datepicker",["mgcrea.ngStrap.helpers.dateParser","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",modelDateFormat:null,dayFormat:"dd",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","$locale","dateFilter","datepickerViews","$tooltip","$timeout",function(t,n,a,o,i,r,s,l,u){function c(t,n,a){function o(e){e.selected=r.$isSelected(e.date)}function i(){t[0].focus()}var r=l(t,angular.extend({},e,a)),c=a.scope,p=r.$options,g=r.$scope;p.startView&&(p.startView-=p.minView);var m=s(r);r.$views=m.views;var $=m.viewDate;g.$mode=p.startView,g.$iconLeft=p.iconLeft,g.$iconRight=p.iconRight;var h=r.$views[g.$mode];g.$select=function(e){r.select(e)},g.$selectPane=function(e){r.$selectPane(e)},g.$toggleMode=function(){r.setMode((g.$mode+1)%r.$views.length)},r.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())&&(r.$date=e,h.update.call(h,e)),r.$build(!0)},r.updateDisabledDates=function(e){p.disabledDateRanges=e;for(var t=0,n=g.rows.length;n>t;t++)angular.forEach(g.rows[t],r.$setDisabledEl)},r.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&&u(function(){r.hide(!0)})):(angular.extend($,{year:e.getFullYear(),month:e.getMonth(),date:e.getDate()}),r.setMode(g.$mode-1),r.$build())},r.setMode=function(e){g.$mode=e,h=r.$views[g.$mode],r.$build()},r.$build=function(e){e===!0&&h.built||(e!==!1||h.built)&&h.build.call(h)},r.$updateSelected=function(){for(var e=0,t=g.rows.length;t>e;e++)angular.forEach(g.rows[e],o)},r.$isSelected=function(e){return h.isSelected(e)},r.$setDisabledEl=function(e){e.disabled=h.isDisabled(e.date)},r.$selectPane=function(e){var t=h.steps,n=new Date(Date.UTC($.year+(t.year||0)*e,$.month+(t.month||0)*e,$.date+(t.day||0)*e));angular.extend($,{year:n.getUTCFullYear(),month:n.getUTCMonth(),date:n.getUTCDate()}),r.$build()},r.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),f){var t=angular.element(e.target);"button"!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler("click")}},r.$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(){r.setMode(g.$mode-1)}):r.hide(!0);h.onKeyDown(e),c.$digest()}};var v=r.init;r.init=function(){return d&&p.useNative?(t.prop("type","date"),void t.css("-webkit-appearance","textfield")):(f&&(t.prop("type","text"),t.attr("readonly","true"),t.on("click",i)),void v())};var y=r.destroy;r.destroy=function(){d&&p.useNative&&t.off("click",i),y()};var w=r.show;r.show=function(){w(),r.$element.on(f?"touchstart":"mousedown",r.$onMouseDown),p.keyboard&&t.on("keydown",r.$onKeyDown)};var b=r.hide;return r.hide=function(e){r.$isShown&&(r.$element.off(f?"touchstart":"mousedown",r.$onMouseDown),p.keyboard&&t.off("keydown",r.$onKeyDown),b(e))},r}var d=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),f="createTouch"in t.document&&d;return e.lang||(e.lang=i.id),c.defaults=e,c}]}).directive("bsDatepicker",["$window","$parse","$q","$locale","dateFilter","$datepicker","$dateParser",function(e,t,n,a,o,i,r){var s=(i.defaults,/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent));return{restrict:"EAC",require:"ngModel",link:function(e,t,n,a){function l(e){return e&&e.length?e:null}function u(e){if(angular.isDate(e)){var t=isNaN(d.$options.minDate)||e.getTime()>=d.$options.minDate,n=isNaN(d.$options.maxDate)||e.getTime()<=d.$options.maxDate,o=t&&n;a.$setValidity("date",o),a.$setValidity("min",t),a.$setValidity("max",n),o&&(a.$dateValue=e)}}var c={scope:e,controller:a};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","autoclose","dateType","dateFormat","modelDateFormat","dayFormat","strictFormat","startWeek","startDate","useNative","lang","startView","minView","iconLeft","iconRight","daysOfWeekDisabled"],function(e){angular.isDefined(n[e])&&(c[e]=n[e])}),n.bsShow&&e.$watch(n.bsShow,function(e){d&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(datepicker),?/i)),e===!0?d.show():d.hide())});var d=i(t,a,c);c=d.$options,s&&c.useNative&&(c.dateFormat="yyyy-MM-dd");var f=r({format:c.dateFormat,lang:c.lang,strict:c.strictFormat});angular.forEach(["minDate","maxDate"],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){d.$options[e]=f.getDateForAttribute(e,t),!isNaN(d.$options[e])&&d.$build(!1),u(a.$dateValue)})}),e.$watch(n.ngModel,function(){d.update(a.$dateValue)},!0),angular.isDefined(n.disabledDates)&&e.$watch(n.disabledDates,function(e,t){e=l(e),t=l(t),e&&d.updateDisabledDates(e)}),a.$parsers.unshift(function(e){if(!e)return void a.$setValidity("date",!0);var t=f.parse(e,a.$dateValue);return!t||isNaN(t.getTime())?void a.$setValidity("date",!1):(u(t),"string"===c.dateType?o(t,c.modelDateFormat||c.dateFormat):"number"===c.dateType?a.$dateValue.getTime():"iso"===c.dateType?a.$dateValue.toISOString():new Date(a.$dateValue))}),a.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:"string"===c.dateType?f.parse(e,null,c.modelDateFormat):new Date(e),a.$dateValue=t,a.$dateValue}),a.$render=function(){t.val(!a.$dateValue||isNaN(a.$dateValue.getTime())?"":o(a.$dateValue,c.dateFormat))},e.$on("$destroy",function(){d&&d.destroy(),c=null,d=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=["$locale","$sce","dateFilter","$dateParser",function(n,a,o,i){return function(r){var s=r.$scope,l=r.$options,u=i(),c=n.DATETIME_FORMATS.SHORTDAY,d=c.slice(l.startWeek).concat(c.slice(0,l.startWeek)),f=a.trustAsHtml(''+d.join(' ')+" "),p=r.$date||(l.startDate?u.getDateForAttribute("startDate",l.startDate):new Date),g={year:p.getFullYear(),month:p.getMonth(),date:p.getDate()},m=(6e4*p.getTimezoneOffset(),[{format:l.dayFormat,split:7,steps:{month:1},update:function(e,t){!this.built||t||e.getFullYear()!==g.year||e.getMonth()!==g.month?(angular.extend(g,{year:r.$date.getFullYear(),month:r.$date.getMonth(),date:r.$date.getDate()}),r.$build()):e.getDate()!==g.date&&(g.date=r.$date.getDate(),r.$updateSelected())},build:function(){var n=new Date(g.year,g.month,1),a=n.getTimezoneOffset(),i=new Date(+n-864e5*t(n.getDay()-l.startWeek,7)),u=i.getTimezoneOffset(),c=(new Date).toDateString();u!==a&&(i=new Date(+i+6e4*(u-a)));for(var d,p=[],m=0;42>m;m++)d=new Date(i.getFullYear(),i.getMonth(),i.getDate()+m),p.push({date:d,isToday:d.toDateString()===c,label:o(d,this.format),selected:r.$date&&this.isSelected(d),muted:d.getMonth()!==g.month,disabled:this.isDisabled(d)});s.title=o(n,"MMMM yyyy"),s.showLabels=!0,s.labels=f,s.rows=e(p,this.split),this.built=!0},isSelected:function(e){return r.$date&&e.getFullYear()===r.$date.getFullYear()&&e.getMonth()===r.$date.getMonth()&&e.getDate()===r.$date.getDate()},isDisabled:function(e){var t=e.getTime();if(tl.maxDate)return!0;if(-1!==l.daysOfWeekDisabled.indexOf(e.getDay()))return!0;if(l.disabledDateRanges)for(var n=0;n=l.disabledDateRanges[n].start&&t<=l.disabledDateRanges[n].end)return!0;return!1},onKeyDown:function(e){if(r.$date){var t,n=r.$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)||r.select(t,!0)}}},{name:"month",format:"MMM",split:4,steps:{year:1},update:function(e){this.built&&e.getFullYear()===g.year?e.getMonth()!==g.month&&(angular.extend(g,{month:r.$date.getMonth(),date:r.$date.getDate()}),r.$updateSelected()):(angular.extend(g,{year:r.$date.getFullYear(),month:r.$date.getMonth(),date:r.$date.getDate()}),r.$build())},build:function(){for(var t,n=(new Date(g.year,0,1),[]),a=0;12>a;a++)t=new Date(g.year,a,1),n.push({date:t,label:o(t,this.format),selected:r.$isSelected(t),disabled:this.isDisabled(t)});s.title=o(t,"yyyy"),s.showLabels=!1,s.rows=e(n,this.split),this.built=!0},isSelected:function(e){return r.$date&&e.getFullYear()===r.$date.getFullYear()&&e.getMonth()===r.$date.getMonth()},isDisabled:function(e){var t=+new Date(e.getFullYear(),e.getMonth()+1,0);return tl.maxDate},onKeyDown:function(e){if(r.$date){var t=r.$date.getMonth(),n=new Date(r.$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)||r.select(n,!0)}}},{name:"year",format:"yyyy",split:4,steps:{year:12},update:function(e,t){!this.built||t||parseInt(e.getFullYear()/20,10)!==parseInt(g.year/20,10)?(angular.extend(g,{year:r.$date.getFullYear(),month:r.$date.getMonth(),date:r.$date.getDate()}),r.$build()):e.getFullYear()!==g.year&&(angular.extend(g,{year:r.$date.getFullYear(),month:r.$date.getMonth(),date:r.$date.getDate()}),r.$updateSelected())},build:function(){for(var t,n=g.year-g.year%(3*this.split),a=[],i=0;12>i;i++)t=new Date(n+i,0,1),a.push({date:t,label:o(t,this.format),selected:r.$isSelected(t),disabled:this.isDisabled(t)});s.title=a[0].label+"-"+a[a.length-1].label,s.showLabels=!1,s.rows=e(a,this.split),this.built=!0},isSelected:function(e){return r.$date&&e.getFullYear()===r.$date.getFullYear()},isDisabled:function(e){var t=+new Date(e.getFullYear()+1,0,0);return tl.maxDate},onKeyDown:function(e){if(r.$date){var t=r.$date.getFullYear(),n=new Date(r.$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)||r.select(n,!0)}}}]);return{views:l.minView?Array.prototype.slice.call(m,l.minView):m,viewDate:g}}}]}),angular.module("mgcrea.ngStrap.dropdown",["mgcrea.ngStrap.tooltip"]).provider("$dropdown",function(){var e=this.defaults={animation:"am-fade",prefixClass:"dropdown",placement:"bottom-left",template:"dropdown/dropdown.tpl.html",trigger:"click",container:!1,keyboard:!0,html:!1,delay:0};this.$get=["$window","$rootScope","$tooltip",function(t,n,a){function o(t,o){function s(e){return e.target!==t[0]?e.target!==t[0]&&l.hide():void 0}{var l={},u=angular.extend({},e,o);l.$scope=u.scope&&u.scope.$new()||n.$new()}l=a(t,u);var c=t.parent();l.$onKeyDown=function(e){if(/(38|40)/.test(e.keyCode)){e.preventDefault(),e.stopPropagation();var t=angular.element(l.$element[0].querySelectorAll("li:not(.divider) a"));if(t.length){var n;angular.forEach(t,function(e,t){r&&r.call(e,":focus")&&(n=t)}),38===e.keyCode&&n>0?n--:40===e.keyCode&&no;o++)if(e[o].toLowerCase()===a)return o;return-1}e.prototype.setMilliseconds=function(e){this.milliseconds=e},e.prototype.setSeconds=function(e){this.seconds=e},e.prototype.setMinutes=function(e){this.minutes=e},e.prototype.setHours=function(e){this.hours=e},e.prototype.getHours=function(){return this.hours},e.prototype.setDate=function(e){this.day=e},e.prototype.setMonth=function(e){this.month=e},e.prototype.setFullYear=function(e){this.year=e},e.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},e.prototype.toDate=function(){return new Date(this.year,this.month,this.day,this.hours,this.minutes,this.seconds,this.milliseconds)};var o=e.prototype,i=this.defaults={format:"shortDate",strict:!1};this.$get=["$locale","dateFilter",function(r,s){var l=function(l){function u(e){var t,n=Object.keys(h),a=[],o=[],i=e;for(t=0;t1){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 ');return s.$promise.then(function(e){angular.isObject(e)&&(e=e.data),u.html&&(e=e.replace(v,'ng-bind-html="')),e=m.apply(e),y=o(e),s.init()}),s.init=function(){u.show&&d.$$postDigest(function(){s.show()})},s.destroy=function(){w&&(w.remove(),w=null),b&&(b.remove(),b=null),d.$destroy()},s.show=function(){if(!d.$isShown&&!d.$emit(u.prefixEvent+".show.before",s).defaultPrevented){var e;e=angular.isElement(u.container)?u.container:u.container?f(u.container):null;
-var t=u.container?null:u.element;w=s.$element=y(d,function(){}),w.css({display:"block"}).addClass(u.placement),u.animation&&(u.backdrop&&b.addClass(u.backdropAnimation),w.addClass(u.animation)),u.backdrop&&l.enter(b,h,null);var a=l.enter(w,e,t,n);a&&a.then&&a.then(n),d.$isShown=!0,d.$$phase||d.$root&&d.$root.$$phase||d.$digest();var o=w[0];$(function(){o.focus()}),h.addClass(u.prefixClass+"-open"),u.animation&&h.addClass(u.prefixClass+"-with-"+u.animation),u.backdrop&&(w.on("click",r),b.on("click",r)),u.keyboard&&w.on("keyup",s.$onKeyUp)}},s.hide=function(){if(d.$isShown&&!d.$emit(u.prefixEvent+".hide.before",s).defaultPrevented){var e=l.leave(w,i);e&&e.then&&e.then(i),u.backdrop&&l.leave(b),d.$isShown=!1,d.$$phase||d.$root&&d.$root.$$phase||d.$digest(),u.backdrop&&(w.off("click",r),b.off("click",r)),u.keyboard&&w.off("keyup",s.$onKeyUp)}},s.toggle=function(){d.$isShown?s.hide():s.show()},s.focus=function(){w[0].focus()},s.$onKeyUp=function(e){27===e.which&&d.$isShown&&(s.hide(),e.stopPropagation())},s}function f(e,n){return angular.element((n||t).querySelectorAll(e))}function p(e){return i.when(r.get(e)||s.get(e)).then(function(t){return angular.isObject(t)?(r.put(e,t.data),t.data):t})}var g=angular.forEach,m=String.prototype.trim,$=n.requestAnimationFrame||n.setTimeout,h=angular.element(n.document.body),v=/ng-bind="/gi;return d}]}).directive("bsModal",["$window","$sce","$modal",function(e,t,n){return{restrict:"EAC",scope:!0,link:function(e,a,o){var i={scope:e,element:a,show:!1};angular.forEach(["template","contentTemplate","placement","backdrop","keyboard","html","container","animation"],function(e){angular.isDefined(o[e])&&(i[e]=o[e])}),angular.forEach(["title","content"],function(n){o[n]&&o.$observe(n,function(a){e[n]=t.trustAsHtml(a)})}),o.bsModal&&e.$watch(o.bsModal,function(t){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var r=n(i);a.on(o.trigger||"click",r.toggle),e.$on("$destroy",function(){r&&r.destroy(),i=null,r=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){var i=angular.copy(a);angular.forEach(Object.keys(a),function(e){angular.isDefined(o[e])&&(i[e]=o[e])}),e.$watch(function(){return t.path()},function(e){var t=n[0].querySelectorAll("li["+i.routeAttr+"]");angular.forEach(t,function(t){var n=angular.element(t),a=n.attr(i.routeAttr).replace("/","\\/");i.strict&&(a="^"+a+"$");var o=new RegExp(a,["i"]);o.test(e)?n.addClass(i.activeClass):n.removeClass(i.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","target","delay","trigger","keyboard","html","animation","customClass","autoClose"],function(e){angular.isDefined(i[e])&&(r[e]=i[e])}),angular.forEach(["title","content"],function(n){i[n]&&i.$observe(n,function(o,i){e[n]=t.trustAsHtml(o),angular.isDefined(i)&&a(function(){s&&s.$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(){s&&s.$applyPlacement()})},!0),i.bsShow&&e.$watch(i.bsShow,function(e){s&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(popover),?/i)),e===!0?s.show():s.hide())});var s=n(o,r);e.$on("$destroy",function(){s&&s.destroy(),r=null,s=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,y,w,b,D,k,S,T={},x=T.$trackedElements=[],C=[];return T.init=function(){this.$$count=1,w=s(this.checkPosition,c.debounce),b=l(this.checkPosition,c.throttle),m.on("click",this.checkPositionWithEventLoop),d.on("resize",w),m.on("scroll",b),D=s(this.checkOffsets,c.debounce),h=i.$on("$viewContentLoaded",D),v=i.$on("$includeContentLoaded",D),D(),$&&(e[$]=T)},T.destroy=function(){this.$$count--,this.$$count>0||(m.off("click",this.checkPositionWithEventLoop),d.off("resize",w),m.off("scroll",w),h(),v(),$&&delete e[$])},T.checkPosition=function(){if(C.length){if(S=(g?a.pageYOffset:m.prop("scrollTop"))||0,k=Math.max(a.innerHeight,f.prop("clientHeight")),SC[e+1].offsetTop))return T.$activateElement(C[e])}},T.checkPositionWithEventLoop=function(){setTimeout(this.checkPosition,1)},T.$activateElement=function(e){if(y){var t=T.$getTrackedElement(y);t&&(t.source.removeClass("active"),u(t.source,"li")&&u(t.source.parent().parent(),"li")&&t.source.parent().parent().removeClass("active"))}y=e.target,e.source.addClass("active"),u(e.source,"li")&&u(e.source.parent().parent(),"li")&&e.source.parent().parent().addClass("active")},T.$getTrackedElement=function(e){return x.filter(function(t){return t.target===e})[0]},T.checkOffsets=function(){angular.forEach(x,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=x.filter(function(e){return null!==e.offsetTop}).sort(function(e,t){return e.offsetTop-t.offsetTop}),w()},T.trackElement=function(e,t){x.push({target:e,source:t})},T.untrackElement=function(e,t){for(var n,a=x.length;a--;)if(x[a].target===e&&x[a].source===t){n=a;break}x=x.splice(n,1)},T.activate=function(e){x[e].addClass("active")},T.init(),T}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(){return{restrict:"A",compile:function(e){var t=e[0].querySelectorAll("li > a[href]");angular.forEach(t,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:' ',placeholder:"Choose among the following...",maxLength:3,maxLengthHtml:"selected",iconCheckmark:"glyphicon glyphicon-ok"};this.$get=["$window","$document","$rootScope","$tooltip",function(t,n,a,o){function i(t,n,a){var i={},r=angular.extend({},e,a);i=o(t,r);var l=i.$scope;l.$matches=[],l.$activeIndex=0,l.$isMultiple=r.multiple,l.$showAllNoneButtons=r.allNoneButtons&&r.multiple,l.$iconCheckmark=r.iconCheckmark,l.$activate=function(e){l.$$postDigest(function(){i.activate(e)})},l.$select=function(e){l.$$postDigest(function(){i.select(e)})},l.$isVisible=function(){return i.$isVisible()},l.$isActive=function(e){return i.$isActive(e)},l.$selectAll=function(){for(var e=0;e=l.$matches.length&&(l.$activeIndex=r.multiple?[]:0)},i.$isVisible=function(){return r.minLength&&n?l.$matches.length&&n.$viewValue.length>=r.minLength:l.$matches.length},i.$isActive=function(e){return r.multiple?-1!==l.$activeIndex.indexOf(e):l.$activeIndex===e},i.$getIndex=function(e){var t=l.$matches.length,n=t;if(t){for(n=t;n--&&l.$matches[n].value!==e;);if(!(0>n))return n}},i.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),s){var t=angular.element(e.target);t.triggerHandler("click")}},i.$onKeyDown=function(e){if(/(9|13|38|40)/.test(e.keyCode)){if(e.preventDefault(),e.stopPropagation(),!r.multiple&&(13===e.keyCode||9===e.keyCode))return i.select(l.$activeIndex);38===e.keyCode&&l.$activeIndex>0?l.$activeIndex--:40===e.keyCode&&l.$activeIndex'),l.after(t)}var u=o(n.ngOptions),c=a(t,r,s),d=u.$match[7].replace(/\|.+/,"").trim();e.$watch(d,function(){u.valuesFn(e,r).then(function(e){c.update(e),r.$render()})},!0),e.$watch(n.ngModel,function(){c.$updateActiveIndex(),r.$render()},!0),r.$render=function(){var e,n;s.multiple&&angular.isArray(r.$modelValue)?(e=r.$modelValue.map(function(e){return n=c.$getIndex(e),angular.isDefined(n)?c.$scope.$matches[n].label:!1}).filter(angular.isDefined),e=e.length>(s.maxLength||i.maxLength)?e.length+" "+(s.maxLengthHtml||i.maxLengthHtml):e.join(", ")):(n=c.$getIndex(r.$modelValue),e=angular.isDefined(n)?c.$scope.$matches[n].label:!1),t.html((e?e:s.placeholder)+i.caretHtml)},e.$on("$destroy",function(){c&&c.destroy(),s=null,c=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.$viewChangeListeners=[],o.$push=function(e){o.$panes.push(e)},o.$remove=function(e){var t=o.$panes.indexOf(e),n=o.$panes.$active;o.$panes.splice(t,1),n>t?n--:t===n&&n===o.$panes.length&&n--,o.$setActive(n)},o.$panes.$active=0,o.$setActive=t.$setActive=function(e){o.$panes.$active=e,o.$viewChangeListeners.forEach(function(e){e()})}};this.$get=function(){var n={};return n.defaults=e,n.controller=t,n}}).directive("bsTabs",["$window","$animate","$tab",function(e,t,n){var a=n.defaults;return{require:["?ngModel","bsTabs"],transclude:!0,scope:!0,controller:["$scope","$element","$attrs",n.controller],templateUrl:function(e,t){return t.template||a.template},link:function(e,t,n,a){var o=a[0],i=a[1];o&&(i.$viewChangeListeners.push(function(){o.$setViewValue(i.$panes.$active)}),o.$formatters.push(function(e){return i.$setActive(1*e),e}))}}}]).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),o=s.$panes.$active;t[n===o?"addClass":"removeClass"](a,s.$options.activeClass)}var s=(i[0],i[1]);a.addClass("tab-pane"),o.$observe("title",function(t){e.title=n.trustAsHtml(t)}),s.$options.animation&&a.addClass(s.$options.animation),s.$push(e),e.$on("$destroy",function(){s.$remove(e)}),s.$viewChangeListeners.push(function(){r()}),r()}}}]),angular.module("mgcrea.ngStrap.timepicker",["mgcrea.ngStrap.helpers.dateParser","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",modelTimeFormat:null,autoclose:!1,minTime:-1/0,maxTime:+1/0,length:5,hourStep:1,minuteStep:5,iconUp:"glyphicon glyphicon-chevron-up",iconDown:"glyphicon glyphicon-chevron-down",arrowBehavior:"pager"};this.$get=["$window","$document","$rootScope","$sce","$locale","dateFilter","$tooltip","$timeout",function(t,n,a,o,i,r,s,l){function u(t,n,a){function o(e,n){if(t[0].createTextRange){var a=t[0].createTextRange();a.collapse(!0),a.moveStart("character",e),a.moveEnd("character",n),a.select()}else t[0].setSelectionRange?t[0].setSelectionRange(e,n):angular.isUndefined(t[0].selectionStart)&&(t[0].selectionStart=e,t[0].selectionEnd=n)}function u(){t[0].focus()}var f=s(t,angular.extend({},e,a)),p=a.scope,g=f.$options,m=f.$scope,$=0,h=n.$dateValue||new Date,v={hour:h.getHours(),meridian:h.getHours()<12,minute:h.getMinutes(),second:h.getSeconds(),millisecond:h.getMilliseconds()},y=i.DATETIME_FORMATS[g.timeFormat]||g.timeFormat,w=/(h+)([:\.])?(m+)[ ]?(a?)/i.exec(y).slice(1);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(v,{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()),n.$setViewValue(angular.copy(n.$dateValue)),n.$render(),g.autoclose&&!a&&l(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;e1*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=(r(n,"h").length,n.getMinutes());r(n,"mm").length}0===t?n.setHours(a-parseInt(g.hourStep,10)*e):n.setMinutes(o-parseInt(g.minuteStep,10)*e),f.select(n,t,!0)},f.$moveIndex=function(e,t){var n;0===t?(n=new Date(1970,0,1,v.hour+e*g.length,v.minute),angular.extend(v,{hour:n.getHours()})):1===t&&(n=new Date(1970,0,1,v.hour,v.minute+e*g.length*g.minuteStep),angular.extend(v,{minute:n.getMinutes()})),f.$build()},f.$onMouseDown=function(e){if("input"!==e.target.nodeName.toLowerCase()&&e.preventDefault(),e.stopPropagation(),d){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=r(t,"h").length,i=t.getMinutes(),s=r(t,"mm").length,l=/(37|39)/.test(e.keyCode),u=2+1*!!w[3];l&&(37===e.keyCode?$=1>$?u-1:$-1:39===e.keyCode&&($=u-1>$?$+1:0));var c=[0,a];0===$?(38===e.keyCode?t.setHours(n-parseInt(g.hourStep,10)):40===e.keyCode&&t.setHours(n+parseInt(g.hourStep,10)),c=[0,a]):1===$?(38===e.keyCode?t.setMinutes(i-parseInt(g.minuteStep,10)):40===e.keyCode&&t.setMinutes(i+parseInt(g.minuteStep,10)),c=[a+1,a+1+s]):2===$&&(l||f.switchMeridian(),c=[a+1+s+1,a+1+s+3]),f.select(t,$,!0),o(c[0],c[1]),p.$digest()}};var b=f.init;f.init=function(){return c&&g.useNative?(t.prop("type","time"),void t.css("-webkit-appearance","textfield")):(d&&(t.prop("type","text"),t.attr("readonly","true"),t.on("click",u)),void b())};var D=f.destroy;f.destroy=function(){c&&g.useNative&&t.off("click",u),D()};var k=f.show;f.show=function(){k(),f.$element.on(d?"touchstart":"mousedown",f.$onMouseDown),g.keyboard&&t.on("keydown",f.$onKeyDown)};var S=f.hide;return f.hide=function(e){f.$isShown&&(f.$element.off(d?"touchstart":"mousedown",f.$onMouseDown),g.keyboard&&t.off("keydown",f.$onKeyDown),S(e))},f}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.id),u.defaults=e,u}]}).directive("bsTimepicker",["$window","$parse","$q","$locale","dateFilter","$timepicker","$dateParser",function(e,t,n,a,o,i,r){{var s=i.defaults,l=/(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,a){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,o=t&&n;a.$setValidity("date",o),a.$setValidity("min",t),a.$setValidity("max",n),o&&(a.$dateValue=e)}}function c(){return!a.$dateValue||isNaN(a.$dateValue.getTime())?"":o(a.$dateValue,d.timeFormat)}var d={scope:e,controller:a};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","autoclose","timeType","timeFormat","modelTimeFormat","useNative","hourStep","minuteStep","length","arrowBehavior","iconUp","iconDown"],function(e){angular.isDefined(n[e])&&(d[e]=n[e])}),n.bsShow&&e.$watch(n.bsShow,function(e){f&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(timepicker),?/i)),e===!0?f.show():f.hide())}),l&&(d.useNative||s.useNative)&&(d.timeFormat="HH:mm");var f=i(t,a,d);d=f.$options;var p=r({format:d.timeFormat,lang:d.lang});angular.forEach(["minTime","maxTime"],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){f.$options[e]=p.getTimeForAttribute(e,t),!isNaN(f.$options[e])&&f.$build(),u(a.$dateValue)})}),e.$watch(n.ngModel,function(){f.update(a.$dateValue)},!0),a.$parsers.unshift(function(e){if(!e)return void a.$setValidity("date",!0);var t=angular.isDate(e)?e:p.parse(e,a.$dateValue);return!t||isNaN(t.getTime())?void a.$setValidity("date",!1):(u(t),"string"===d.timeType?o(t,d.modelTimeFormat||d.timeFormat):"number"===d.timeType?a.$dateValue.getTime():"iso"===d.timeType?a.$dateValue.toISOString():new Date(a.$dateValue))}),a.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:"string"===d.timeType?p.parse(e,null,d.modelTimeFormat):new Date(e),a.$dateValue=t,c()}),a.$render=function(){t.val(c())},e.$on("$destroy",function(){f&&f.destroy(),d=null,f=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};this.$get=["$window","$rootScope","$compile","$q","$templateCache","$http","$animate","dimensions","$$rAF","$timeout",function(n,a,o,i,r,s,l,u,c,d){function f(t,n){function i(){k.$emit(D.prefixEvent+".show",w)}function r(){return k.$emit(D.prefixEvent+".hide",w),F&&"focus"===D.trigger?t[0].blur():void y()}function s(){return"body"===D.container?u.offset(D.target[0]||t[0]):u.position(D.target[0]||t[0])}function f(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":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 y(){clearTimeout(T),V&&(V.$destroy(),V=null),M&&(M.remove(),M=w.$element=null)}var w={},b=t[0].nodeName.toLowerCase(),D=w.$options=angular.extend({},e,n);w.$promise=g(D.template);var k=w.$scope=D.scope&&D.scope.$new()||a.$new();if(D.delay&&angular.isString(D.delay)){var S=D.delay.split(",").map(parseFloat);D.delay=S.length>1?{show:S[0],hide:S[1]}:S[0]}D.title&&(w.$scope.title=D.title),k.$setEnabled=function(e){k.$$postDigest(function(){w.setEnabled(e)})},k.$hide=function(){k.$$postDigest(function(){w.hide()})},k.$show=function(){k.$$postDigest(function(){w.show()})},k.$toggle=function(){k.$$postDigest(function(){w.toggle()})},w.$isShown=k.$isShown=!1;var T,x;D.contentTemplate&&(w.$promise=w.$promise.then(function(e){var t=angular.element(e);return g(D.contentTemplate).then(function(e){var n=p('[ng-bind="content"]',t[0]);return n.length||(n=p('[ng-bind="title"]',t[0])),n.removeAttr("ng-bind").html(e),t[0].outerHTML})}));var C,M,E,A,V;w.$promise.then(function(e){angular.isObject(e)&&(e=e.data),D.html&&(e=e.replace(h,'ng-bind-html="')),e=m.apply(e),E=e,C=o(e),w.init()}),w.init=function(){D.delay&&angular.isNumber(D.delay)&&(D.delay={show:D.delay,hide:D.delay}),"self"===D.container?A=t:angular.isElement(D.container)?A=D.container:D.container&&(A=p(D.container));var e=D.trigger.split(" ");angular.forEach(e,function(e){"click"===e?t.on("click",w.toggle):"manual"!==e&&(t.on("hover"===e?"mouseenter":"focus",w.enter),t.on("hover"===e?"mouseleave":"blur",w.leave),"button"===b&&"hover"!==e&&t.on($?"touchstart":"mousedown",w.$onFocusElementMouseDown))}),D.target&&(D.target=angular.isElement(D.target)?D.target:p(D.target)),D.show&&k.$$postDigest(function(){"focus"===D.trigger?t[0].focus():w.show()})},w.destroy=function(){for(var e=D.trigger.split(" "),n=e.length;n--;){var a=e[n];"click"===a?t.off("click",w.toggle):"manual"!==a&&(t.off("hover"===a?"mouseenter":"focus",w.enter),t.off("hover"===a?"mouseleave":"blur",w.leave),"button"===b&&"hover"!==a&&t.off($?"touchstart":"mousedown",w.$onFocusElementMouseDown))}D.autoClose&&w.$isShown&&null!==M&&(v.off("click"),M.off("click")),y(),k.$destroy()},w.enter=function(){return clearTimeout(T),x="in",D.delay&&D.delay.show?void(T=setTimeout(function(){"in"===x&&w.show()},D.delay.show)):w.show()},w.show=function(){if(D.bsEnabled){k.$emit(D.prefixEvent+".show.before",w);var e=D.container?A:null,n=D.container?null:t;M&&y(),V=w.$scope.$new(),M=w.$element=C(V,function(){}),M.css({top:"-9999px",left:"-9999px",display:"block",visibility:"hidden"}).addClass(D.placement),D.animation&&M.addClass(D.animation),D.type&&M.addClass(D.prefixClass+"-"+D.type),D.customClass&&M.addClass(D.customClass);var a=l.enter(M,e,n,i);a&&a.then&&a.then(i),w.$isShown=k.$isShown=!0,k.$$phase||k.$root&&k.$root.$$phase||k.$digest(),c(function(){w.$applyPlacement(),M&&M.css({visibility:"visible"})}),D.keyboard&&("focus"!==D.trigger?(w.focus(),M.on("keyup",w.$onKeyUp)):t.on("keyup",w.$onFocusKeyUp)),D.autoClose&&(M.on("click",function(e){e.stopPropagation()}),d(function(){v.on("click",function(){w.hide()})},0,!1))}},w.leave=function(){return clearTimeout(T),x="out",D.delay&&D.delay.hide?void(T=setTimeout(function(){"out"===x&&w.hide()},D.delay.hide)):w.hide()};var F;return w.hide=function(e){if(w.$isShown){k.$emit(D.prefixEvent+".hide.before",w),F=e;var t=l.leave(M,r);t&&t.then&&t.then(r),w.$isShown=k.$isShown=!1,k.$$phase||k.$root&&k.$root.$$phase||k.$digest(),D.keyboard&&null!==M&&M.off("keyup",w.$onKeyUp),D.autoClose&&null!==M&&(v.off("click"),M.off("click"))}},w.toggle=function(){w.$isShown?w.leave():w.enter()},w.focus=function(){M[0].focus()},w.setEnabled=function(e){D.bsEnabled=e},w.$applyPlacement=function(){if(M){var e=s(),t=M.prop("offsetWidth"),n=M.prop("offsetHeight"),a=f(D.placement,e,t,n);a.top+="px",a.left+="px",M.css(a)}},w.$onKeyUp=function(e){27===e.which&&w.$isShown&&(w.hide(),e.stopPropagation())},w.$onFocusKeyUp=function(e){27===e.which&&(t[0].blur(),e.stopPropagation())},w.$onFocusElementMouseDown=function(e){e.preventDefault(),e.stopPropagation(),w.$isShown?t[0].blur():t[0].focus()},w}function p(e,n){return angular.element((n||t).querySelectorAll(e))}function g(e){return i.when(r.get(e)||s.get(e)).then(function(t){return angular.isObject(t)?(r.put(e,t.data),t.data):t})}var m=String.prototype.trim,$="createTouch"in n.document,h=/ng-bind="/gi,v=angular.element(n.document);return f}]}).directive("bsTooltip",["$window","$location","$sce","$tooltip","$$rAF",function(e,t,n,a,o){return{restrict:"EAC",scope:!0,link:function(e,t,i){var r={scope:e};angular.forEach(["template","contentTemplate","placement","container","target","delay","trigger","keyboard","html","animation","type","customClass"],function(e){angular.isDefined(i[e])&&(r[e]=i[e])}),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(){s&&s.$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(){s&&s.$applyPlacement()})},!0),i.bsShow&&e.$watch(i.bsShow,function(e){s&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(tooltip),?/i)),e===!0?s.show():s.hide())}),i.bsEnabled&&e.$watch(i.bsEnabled,function(e){s&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|1|,?(tooltip),?/i)),s.setEnabled(e===!1?!1:!0))});var s=a(t,r);e.$on("$destroy",function(){s&&s.destroy(),r=null,s=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,comparator:""};this.$get=["$window","$rootScope","$tooltip",function(t,n,a){function o(t,n,o){var i={},r=angular.extend({},e,o);i=a(t,r);var s=o.scope,l=i.$scope;l.$resetMatches=function(){l.$matches=[],l.$activeIndex=0},l.$resetMatches(),l.$activate=function(e){l.$$postDigest(function(){i.activate(e)})},l.$select=function(e){l.$$postDigest(function(){i.select(e)})},l.$isVisible=function(){return i.$isVisible()},i.update=function(e){l.$matches=e,l.$activeIndex>=e.length&&(l.$activeIndex=0)},i.activate=function(e){l.$activeIndex=e},i.select=function(e){var t=l.$matches[e].value;n.$setViewValue(t),n.$render(),l.$resetMatches(),s&&s.$digest(),l.$emit(r.prefixEvent+".select",t,e)},i.$isVisible=function(){return r.minLength&&n?l.$matches.length&&angular.isString(n.$viewValue)&&n.$viewValue.length>=r.minLength:!!l.$matches.length},i.$getIndex=function(e){var t=l.$matches.length,n=t;if(t){for(n=t;n--&&l.$matches[n].value!==e;);if(!(0>n))return n}},i.$onMouseDown=function(e){e.preventDefault(),e.stopPropagation()},i.$onKeyDown=function(e){/(38|40|13)/.test(e.keyCode)&&(i.$isVisible()&&(e.preventDefault(),e.stopPropagation()),13===e.keyCode&&l.$matches.length?i.select(l.$activeIndex):38===e.keyCode&&l.$activeIndex>0?l.$activeIndex--:40===e.keyCode&&l.$activeIndex0)return void s.$setViewValue(s.$viewValue.substring(0,s.$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),s.$render())})}),s.$formatters.push(function(e){var t=p.displayValue(e);return t===n?"":t}),s.$render=function(){if(s.$isEmpty(s.$viewValue))return t.val("");var e=g.$getIndex(s.$modelValue),n=angular.isDefined(e)?g.$scope.$matches[e].label:s.$viewValue;n=angular.isObject(n)?n.label:n,t.val(n?n.toString().replace(/<(?:.|\n)*?>/gm,"").trim():"")},e.$on("$destroy",function(){g&&g.destroy(),l=null,g=null
-})}}}])}(window,document);
+!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"};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!==y&&t.top+n+$>=o-y?"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,m="affix affix-top affix-bottom",g=!1,$=0,h=0,v=0,y=0,w=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+$,g=!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);w!==r&&(w=r,o.removeClass(m).addClass("affix"+("middle"!==r?"-"+r:"")),"top"===r?(b=null,o.css("position",f.offsetParent?"":"relative"),g&&o.css("width",""),o.css("top","")):"bottom"===r?(b=f.offsetUnpin?-(1*f.offsetUnpin):t.top-e,g&&o.css("width",""),o.css("position",f.offsetParent?"":"relative"),o.css("top",f.offsetParent?"":i[0].offsetHeight-y-n-h+"px")):(b=null,g&&o.css("width",o[0].offsetWidth+"px"),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");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&&(y=f.offsetParent&&f.offsetBottom.match(/^[-+]\d+$/)?c()-(a.offset(D[0]).top+a.height(D[0]))+1*f.offsetBottom+1:1*f.offsetBottom),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,offsetTop:"auto",target:i?i.$element:angular.element(t)};angular.forEach(["offsetTop","offsetBottom","offsetParent","offsetUnpin"],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});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){var i={scope:e,element:a,show:!1};angular.forEach(["template","placement","keyboard","html","container","animation","duration","dismissable"],function(e){angular.isDefined(o[e])&&(i[e]=o[e])}),angular.forEach(["title","content","type"],function(n){o[n]&&o.$observe(n,function(a){e[n]=t.trustAsHtml(a)})}),o.bsAlert&&e.$watch(o.bsAlert,function(t){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var r=n(i);a.on(o.trigger||"click",r.toggle),e.$on("$destroy",function(){r&&r.destroy(),i=null,r=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){var i={scope:e,element:a,show:!1};angular.forEach(["template","contentTemplate","placement","backdrop","keyboard","html","container","animation"],function(e){angular.isDefined(o[e])&&(i[e]=o[e])}),angular.forEach(["title","content"],function(n){o[n]&&o.$observe(n,function(a){e[n]=t.trustAsHtml(a)})}),o.bsAside&&e.$watch(o.bsAside,function(t){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var r=n(i);a.on(o.trigger||"click",r.toggle),e.$on("$destroy",function(){r&&r.destroy(),i=null,r=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(){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=n,l="INPUT"===o[0].nodeName,u=l?o.parent():o,c=a.test(i.value)?e.$eval(i.value):i.value;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(){r.$setViewValue(c),r.$render()})})}}}]),angular.module("mgcrea.ngStrap.collapse",[]).provider("$collapse",function(){var e=this.defaults={animation:"am-collapse",disallowToggle:!1,activeClass:"in",startCollapsed:!1},t=this.controller=function(t,n,a){var o=this;o.$options=angular.copy(e),angular.forEach(["animation","disallowToggle","activeClass","startCollapsed"],function(e){angular.isDefined(a[e])&&(o.$options[e]=a[e])}),o.$toggles=[],o.$targets=[],o.$viewChangeListeners=[],o.$registerToggle=function(e){o.$toggles.push(e)},o.$registerTarget=function(e){o.$targets.push(e)},o.$targets.$active=o.$options.startCollapsed?-1:0,o.$setActive=t.$setActive=function(e){o.$targets.$active=o.$options.disallowToggle?e:o.$targets.$active===e?-1:e,o.$viewChangeListeners.forEach(function(e){e()})}};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.$targets.$active)}),o.$formatters.push(function(e){return i.$targets.$active!==1*e&&i.$setActive(1*e),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),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.$targets.$active;e[t===a?"addClass":"removeClass"](n,r.$options.activeClass)}var r=(o[0],o[1]);n.addClass("collapse"),r.$options.animation&&n.addClass(r.$options.animation),r.$registerTarget(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",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,m=u.$scope;p.startView&&(p.startView-=p.minView);var g=r(u);u.$views=g.views;var $=g.viewDate;m.$mode=p.startView,m.$iconLeft=p.iconLeft,m.$iconRight=p.iconRight;var h=u.$views[m.$mode];m.$select=function(e){u.select(e)},m.$selectPane=function(e){u.$selectPane(e)},m.$toggleMode=function(){u.setMode((m.$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=m.rows.length;n>t;t++)angular.forEach(m.rows[t],u.$setDisabledEl)},u.select=function(e,t){angular.isDate(n.$dateValue)||(n.$dateValue=new Date(e)),!m.$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(m.$mode-1),u.$build())},u.setMode=function(e){m.$mode=e,h=u.$views[m.$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=m.rows.length;t>e;e++)angular.forEach(m.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 m.$mode?m.$apply(function(){u.setMode(m.$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 y=u.destroy;u.destroy=function(){c&&p.useNative&&t.off("click",i),y()};var w=u.show;u.show=function(){w(),l(function(){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(f.$options.minDate)||e.getTime()>=f.$options.minDate,n=isNaN(f.$options.maxDate)||e.getTime()<=f.$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","keyboard","html","animation","template","autoclose","dateType","dateFormat","modelDateFormat","dayFormat","strictFormat","startWeek","startDate","useNative","lang","startView","minView","iconLeft","iconRight","daysOfWeekDisabled"],function(e){angular.isDefined(n[e])&&(d[e]=n[e])}),n.bsShow&&e.$watch(n.bsShow,function(e){f&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(datepicker),?/i)),e===!0?f.show():f.hide())});var f=i(t,s,d);d=f.$options,r&&d.useNative&&(d.dateFormat="yyyy-MM-dd");var p=d.lang,m=function(e,t){return a.formatDate(e,t,p)},g=o({format:d.dateFormat,lang:p,strict:d.strictFormat});angular.forEach(["minDate","maxDate"],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){f.$options[e]=g.getDateForAttribute(e,t),!isNaN(f.$options[e])&&f.$build(!1),u(s.$dateValue)})}),e.$watch(n.ngModel,function(){f.update(s.$dateValue)},!0),angular.isDefined(n.disabledDates)&&e.$watch(n.disabledDates,function(e,t){e=l(e),t=l(t),e&&f.updateDisabledDates(e)}),s.$parsers.unshift(function(e){if(!e)return s.$setValidity("date",!0),null;var t=g.parse(e,s.$dateValue);return!t||isNaN(t.getTime())?void s.$setValidity("date",!1):(u(t),"string"===d.dateType?m(t,d.modelDateFormat||d.dateFormat):"number"===d.dateType?s.$dateValue.getTime():"iso"===d.dateType?s.$dateValue.toISOString():new Date(s.$dateValue))}),s.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:"string"===d.dateType?g.parse(e,null,d.modelDateFormat):new Date(e),s.$dateValue=t,c()}),s.$render=function(){t.val(c())},e.$on("$destroy",function(){f&&f.destroy(),d=null,f=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(''+f.join(' ')+" "),m=i.$date||(s.startDate?c.getDateForAttribute("startDate",s.startDate):new Date),g={year:m.getFullYear(),month:m.getMonth(),date:m.getDate()},$=(6e4*m.getTimezoneOffset(),[{format:s.dayFormat,split:7,steps:{month:1},update:function(e,t){!this.built||t||e.getFullYear()!==g.year||e.getMonth()!==g.month?(angular.extend(g,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build()):e.getDate()!==g.date&&(g.date=i.$date.getDate(),i.$updateSelected())},build:function(){var n=new Date(g.year,g.month,1),a=n.getTimezoneOffset(),o=new Date(+n-864e5*t(n.getDay()-s.startWeek,7)),l=o.getTimezoneOffset(),d=(new Date).toDateString();l!==a&&(o=new Date(+o+6e4*(l-a)));for(var f,m=[],$=0;42>$;$++)f=c.daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth(),o.getDate()+$)),m.push({date:f,isToday:f.toDateString()===d,label:u(f,this.format),selected:i.$date&&this.isSelected(f),muted:f.getMonth()!==g.month,disabled:this.isDisabled(f)});r.title=u(n,s.monthTitleFormat),r.showLabels=!0,r.labels=p,r.rows=e(m,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(ts.maxDate)return!0;if(-1!==s.daysOfWeekDisabled.indexOf(e.getDay()))return!0;if(s.disabledDateRanges)for(var n=0;n=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){this.built&&e.getFullYear()===g.year?e.getMonth()!==g.month&&(angular.extend(g,{month:i.$date.getMonth(),date:i.$date.getDate()}),i.$updateSelected()):(angular.extend(g,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build())},build:function(){for(var t,n=(new Date(g.year,0,1),[]),a=0;12>a;a++)t=new Date(g.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 ts.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(g.year/20,10)?(angular.extend(g,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build()):e.getFullYear()!==g.year&&(angular.extend(g,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$updateSelected())},build:function(){for(var t,n=g.year-g.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 ts.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:g}}}]}),angular.module("mgcrea.ngStrap.dropdown",["mgcrea.ngStrap.tooltip"]).provider("$dropdown",function(){var e=this.defaults={animation:"am-fade",prefixClass:"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&&no;o++)if(e[o].toLowerCase()===a)return o;return-1}e.prototype.setMilliseconds=function(e){this.milliseconds=e},e.prototype.setSeconds=function(e){this.seconds=e},e.prototype.setMinutes=function(e){this.minutes=e},e.prototype.setHours=function(e){this.hours=e},e.prototype.getHours=function(){return this.hours},e.prototype.setDate=function(e){this.day=e},e.prototype.setMonth=function(e){this.month=e},e.prototype.setFullYear=function(e){this.year=e},e.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},e.prototype.toDate=function(){return new Date(this.year,this.month,this.day,this.hours,this.minutes,this.seconds,this.milliseconds)};var o=e.prototype,i=this.defaults={format:"shortDate",strict:!1};this.$get=["$locale","dateFilter",function(r,s){var l=function(l){function u(e){var t,n=Object.keys(h),a=[],o=[],i=e;for(t=0;t1){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;t12?e.getHours()+2:0),e):null},g.init(),g};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(){var t=(angular.element,{}),n=t.nodeName=function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()};t.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},t.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)}},t.position=function(e){var o,i,r={top:0,left:0};return"fixed"===t.css(e,"position")?i=e.getBoundingClientRect():(o=a(e),i=t.offset(e),n(o,"html")||(r=t.offset(o)),r.top+=t.css(o,"borderTopWidth",!0),r.left+=t.css(o,"borderLeftWidth",!0)),{width:e.offsetWidth,height:e.offsetHeight,top:i.top-r.top-t.css(e,"marginTop",!0),left:i.left-r.left-t.css(e,"marginLeft",!0)}};var a=function(e){var a=e.ownerDocument,o=e.offsetParent||a;if(n(o,"#document"))return a.documentElement;for(;o&&!n(o,"html")&&"static"===t.css(o,"position");)o=o.offsetParent;return o||a.documentElement};return t.height=function(e,n){var a=e.offsetHeight;return n?a+=t.css(e,"marginTop",!0)+t.css(e,"marginBottom",!0):a-=t.css(e,"paddingTop",!0)+t.css(e,"paddingBottom",!0)+t.css(e,"borderTopWidth",!0)+t.css(e,"borderBottomWidth",!0),a},t.width=function(e,n){var a=e.offsetWidth;return n?a+=t.css(e,"marginLeft",!0)+t.css(e,"marginRight",!0):a-=t.css(e,"paddingLeft",!0)+t.css(e,"paddingRight",!0)+t.css(e,"borderLeftWidth",!0)+t.css(e,"borderRightWidth",!0),a},t}]),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,m;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),m=t(l[7])},r.valuesFn=function(e,t){return n.when(m(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){function d(t){function n(){d.$emit(u.prefixEvent+".show",s)}function i(){d.$emit(u.prefixEvent+".hide",s),v.removeClass(u.prefixClass+"-open"),u.animation&&v.removeClass(u.prefixClass+"-with-"+u.animation)}function r(e){e.target===e.currentTarget&&("static"===u.backdrop?s.focus():s.hide())
+}var s={},u=s.$options=angular.extend({},e,t);s.$promise=m(u.template);var d=s.$scope=u.scope&&u.scope.$new()||a.$new();u.element||u.container||(u.container="body"),g(["title","content"],function(e){u[e]&&(d[e]=c.trustAsHtml(u[e]))}),d.$hide=function(){d.$$postDigest(function(){s.hide()})},d.$show=function(){d.$$postDigest(function(){s.show()})},d.$toggle=function(){d.$$postDigest(function(){s.toggle()})},u.contentTemplate&&(s.$promise=s.$promise.then(function(e){var n=angular.element(e);return m(u.contentTemplate).then(function(e){var a=p('[ng-bind="content"]',n[0]).removeAttr("ng-bind").html(e);return t.template||a.next().remove(),n[0].outerHTML})}));var w,b,D=angular.element('
');return s.$promise.then(function(e){angular.isObject(e)&&(e=e.data),u.html&&(e=e.replace(y,'ng-bind-html="')),e=$.apply(e),w=o(e),s.init()}),s.init=function(){u.show&&d.$$postDigest(function(){s.show()})},s.destroy=function(){b&&(b.remove(),b=null),D&&(D.remove(),D=null),d.$destroy()},s.show=function(){if(!d.$isShown&&!d.$emit(u.prefixEvent+".show.before",s).defaultPrevented){var e,t;angular.isElement(u.container)?(e=u.container,t=u.container[0].lastChild?angular.element(u.container[0].lastChild):null):u.container?(e=p(u.container),t=e[0].lastChild?angular.element(e[0].lastChild):null):(e=null,t=u.element),b=s.$element=w(d,function(){}),b.css({display:"block"}).addClass(u.placement),u.animation&&(u.backdrop&&D.addClass(u.backdropAnimation),b.addClass(u.animation)),u.backdrop&&l.enter(D,v,null);var a=l.enter(b,e,t,n);a&&a.then&&a.then(n),s.$isShown=d.$isShown=!0,f(d);var o=b[0];h(function(){o.focus()}),v.addClass(u.prefixClass+"-open"),u.animation&&v.addClass(u.prefixClass+"-with-"+u.animation),u.backdrop&&(b.on("click",r),D.on("click",r)),u.keyboard&&b.on("keyup",s.$onKeyUp)}},s.hide=function(){if(d.$isShown&&!d.$emit(u.prefixEvent+".hide.before",s).defaultPrevented){var e=l.leave(b,i);e&&e.then&&e.then(i),u.backdrop&&l.leave(D),s.$isShown=d.$isShown=!1,f(d),u.backdrop&&(b.off("click",r),D.off("click",r)),u.keyboard&&b.off("keyup",s.$onKeyUp)}},s.toggle=function(){d.$isShown?s.hide():s.show()},s.focus=function(){b[0].focus()},s.$onKeyUp=function(e){27===e.which&&d.$isShown&&(s.hide(),e.stopPropagation())},s}function f(e){e.$$phase||e.$root&&e.$root.$$phase||e.$digest()}function p(e,n){return angular.element((n||t).querySelectorAll(e))}function m(e){return w[e]?w[e]:w[e]=i.when(r.get(e)||s.get(e)).then(function(t){return angular.isObject(t)?(r.put(e,t.data),t.data):t})}var g=angular.forEach,$=String.prototype.trim,h=n.requestAnimationFrame||n.setTimeout,v=angular.element(n.document.body),y=/ng-bind="/gi,w={};return d}]}).directive("bsModal",["$window","$sce","$modal",function(e,t,n){return{restrict:"EAC",scope:!0,link:function(e,a,o){var i={scope:e,element:a,show:!1};angular.forEach(["template","contentTemplate","placement","backdrop","keyboard","html","container","animation"],function(e){angular.isDefined(o[e])&&(i[e]=o[e])}),angular.forEach(["title","content"],function(n){o[n]&&o.$observe(n,function(a){e[n]=t.trustAsHtml(a)})}),o.bsModal&&e.$watch(o.bsModal,function(t){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var r=n(i);a.on(o.trigger||"click",r.toggle),e.$on("$destroy",function(){r&&r.destroy(),i=null,r=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){var i=angular.copy(a);angular.forEach(Object.keys(a),function(e){angular.isDefined(o[e])&&(i[e]=o[e])}),e.$watch(function(){return t.path()},function(e){var t=n[0].querySelectorAll("li["+i.routeAttr+"]");angular.forEach(t,function(t){var n=angular.element(t),a=n.attr(i.routeAttr).replace("/","\\/");i.strict&&(a="^"+a+"$");var o=new RegExp(a,["i"]);o.test(e)?n.addClass(i.activeClass):n.removeClass(i.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","target","delay","trigger","keyboard","html","animation","customClass","autoClose"],function(e){angular.isDefined(i[e])&&(r[e]=i[e])}),angular.forEach(["title","content"],function(n){i[n]&&i.$observe(n,function(o,i){e[n]=t.trustAsHtml(o),angular.isDefined(i)&&a(function(){s&&s.$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(){s&&s.$applyPlacement()})},!0),i.bsShow&&e.$watch(i.bsShow,function(e){s&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(popover),?/i)),e===!0?s.show():s.hide())});var s=n(o,r);e.$on("$destroy",function(){s&&s.destroy(),r=null,s=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 m=u(c.element,"body"),g=m?d:c.element,$=m?"window":c.id;if(e[$])return e[$].$$count++,e[$];var h,v,y,w,b,D,k,S,T={},C=T.$trackedElements=[],x=[];return T.init=function(){this.$$count=1,w=s(this.checkPosition,c.debounce),b=l(this.checkPosition,c.throttle),g.on("click",this.checkPositionWithEventLoop),d.on("resize",w),g.on("scroll",b),D=s(this.checkOffsets,c.debounce),h=i.$on("$viewContentLoaded",D),v=i.$on("$includeContentLoaded",D),D(),$&&(e[$]=T)},T.destroy=function(){this.$$count--,this.$$count>0||(g.off("click",this.checkPositionWithEventLoop),d.off("resize",w),g.off("scroll",w),h(),v(),$&&delete e[$])},T.checkPosition=function(){if(x.length){if(S=(m?a.pageYOffset:g.prop("scrollTop"))||0,k=Math.max(a.innerHeight,f.prop("clientHeight")),Sx[e+1].offsetTop))return T.$activateElement(x[e])}},T.checkPositionWithEventLoop=function(){setTimeout(T.checkPosition,1)},T.$activateElement=function(e){if(y){var t=T.$getTrackedElement(y);t&&(t.source.removeClass("active"),u(t.source,"li")&&u(t.source.parent().parent(),"li")&&t.source.parent().parent().removeClass("active"))}y=e.target,e.source.addClass("active"),u(e.source,"li")&&u(e.source.parent().parent(),"li")&&e.source.parent().parent().addClass("active")},T.$getTrackedElement=function(e){return C.filter(function(t){return t.target===e})[0]},T.checkOffsets=function(){angular.forEach(C,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)}),x=C.filter(function(e){return null!==e.offsetTop}).sort(function(e,t){return e.offsetTop-t.offsetTop}),w()},T.trackElement=function(e,t){C.push({target:e,source:t})},T.untrackElement=function(e,t){for(var n,a=C.length;a--;)if(C[a].target===e&&C[a].source===t){n=a;break}C=C.splice(n,1)},T.activate=function(e){C[e].addClass("active")},T.init(),T}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(){return{restrict:"A",compile:function(e){var t=e[0].querySelectorAll("li > a[href]");angular.forEach(t,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:' ',placeholder:"Choose among the following...",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=0,u.$isMultiple=s.multiple,u.$showAllNoneButtons=s.allNoneButtons&&s.multiple,u.$iconCheckmark=s.iconCheckmark,u.$activate=function(e){u.$$postDigest(function(){r.activate(e)})},u.$select=function(e){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&&(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){if(/(9|13|38|40)/.test(e.keyCode)){if(e.preventDefault(),e.stopPropagation(),!s.multiple&&(13===e.keyCode||9===e.keyCode))return r.select(u.$activeIndex);38===e.keyCode&&u.$activeIndex>0?u.$activeIndex--:40===e.keyCode&&u.$activeIndex'),l.after(t)}var u=o(n.ngOptions),c=a(t,r,s),d=u.$match[7].replace(/\|.+/,"").trim();e.$watch(d,function(){u.valuesFn(e,r).then(function(e){c.update(e),r.$render()})},!0),e.$watch(n.ngModel,function(){c.$updateActiveIndex(),r.$render()},!0),r.$render=function(){var e,n;s.multiple&&angular.isArray(r.$modelValue)?(e=r.$modelValue.map(function(e){return n=c.$getIndex(e),angular.isDefined(n)?c.$scope.$matches[n].label:!1}).filter(angular.isDefined),e=e.length>(s.maxLength||i.maxLength)?e.length+" "+(s.maxLengthHtml||i.maxLengthHtml):e.join(", ")):(n=c.$getIndex(r.$modelValue),e=angular.isDefined(n)?c.$scope.$matches[n].label:!1),t.html((e?e:s.placeholder)+i.caretHtml)},s.multiple&&(r.$isEmpty=function(e){return!e||0===e.length}),e.$on("$destroy",function(){c&&c.destroy(),s=null,c=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){o.$panes.push(e)},o.$remove=function(e){var t=o.$panes.indexOf(e),n=o.$panes.$active;o.$panes.splice(t,1),n>t?n--:t===n&&n===o.$panes.length&&n--,o.$setActive(n)},o.$panes.$active=0,o.$setActive=t.$setActive=function(e){o.$panes.$active=e,o.$activePaneChangeListeners.forEach(function(e){e()})}};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&&(console.warn("Usage of ngModel is deprecated, please use bsActivePane instead!"),r.$activePaneChangeListeners.push(function(){i.$setViewValue(r.$panes.$active)}),i.$formatters.push(function(e){return r.$setActive(1*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){r.$setActive(1*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),o=s.$panes.$active;t[n===o?"addClass":"removeClass"](a,s.$options.activeClass)}var s=(i[0],i[1]);a.addClass("tab-pane"),o.$observe("title",function(t){e.title=n.trustAsHtml(t)}),s.$options.animation&&a.addClass(s.$options.animation),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",modelTimeFormat:null,autoclose:!1,minTime:-1/0,maxTime:+1/0,length:5,hourStep:1,minuteStep:5,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,n){if(t[0].createTextRange){var a=t[0].createTextRange();a.collapse(!0),a.moveStart("character",e),a.moveEnd("character",n),a.select()}else t[0].setSelectionRange?t[0].setSelectionRange(e,n):angular.isUndefined(t[0].selectionStart)&&(t[0].selectionStart=e,t[0].selectionEnd=n)}function l(){t[0].focus()}var d=r(t,angular.extend({},e,a)),f=a.scope,p=d.$options,m=d.$scope,g=p.lang,$=function(e,t){return i.formatDate(e,t,g)},h=0,v=n.$dateValue||new Date,y={hour:v.getHours(),meridian:v.getHours()<12,minute:v.getMinutes(),second:v.getSeconds(),millisecond:v.getMilliseconds()},w=i.getDatetimeFormat(p.timeFormat,g),b=i.hoursFormat(w),D=i.timeSeparator(w),k=i.minutesFormat(w),S=i.showAM(w);m.$iconUp=p.iconUp,m.$iconDown=p.iconDown,m.$select=function(e,t){d.select(e,t)},m.$moveIndex=function(e,t){d.$moveIndex(e,t)},m.$switchMeridian=function(e){d.switchMeridian(e)},d.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())?(d.$date=e,angular.extend(y,{hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}),d.$build()):d.$isBuilt||d.$build()},d.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()),n.$setViewValue(angular.copy(n.$dateValue)),n.$render(),p.autoclose&&!a&&s(function(){d.hide(!0)})},d.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()}},d.$build=function(){var e,t,n=m.midIndex=parseInt(p.length/2,10),a=[];for(e=0;e1*p.maxTime},m.$arrowAction=function(e,t){"picker"===p.arrowBehavior?d.$setTimeByStep(e,t):d.$moveIndex(e,t)},d.$setTimeByStep=function(e,t){{var n=new Date(d.$date),a=n.getHours(),o=($(n,b).length,n.getMinutes());$(n,k).length}0===t?n.setHours(a-parseInt(p.hourStep,10)*e):n.setMinutes(o-parseInt(p.minuteStep,10)*e),d.select(n,t,!0)},d.$moveIndex=function(e,t){var n;0===t?(n=new Date(1970,0,1,y.hour+e*p.length,y.minute),angular.extend(y,{hour:n.getHours()})):1===t&&(n=new Date(1970,0,1,y.hour,y.minute+e*p.length*p.minuteStep),angular.extend(y,{minute:n.getMinutes()})),d.$build()},d.$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")}},d.$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 d.hide(!0);var t=new Date(d.$date),n=t.getHours(),a=$(t,b).length,i=t.getMinutes(),r=$(t,k).length,s=/(37|39)/.test(e.keyCode),l=2+1*S;s&&(37===e.keyCode?h=1>h?l-1:h-1:39===e.keyCode&&(h=l-1>h?h+1:0));var u=[0,a];0===h?(38===e.keyCode?t.setHours(n-parseInt(p.hourStep,10)):40===e.keyCode&&t.setHours(n+parseInt(p.hourStep,10)),a=$(t,b).length,u=[0,a]):1===h?(38===e.keyCode?t.setMinutes(i-parseInt(p.minuteStep,10)):40===e.keyCode&&t.setMinutes(i+parseInt(p.minuteStep,10)),r=$(t,k).length,u=[a+1,a+1+r]):2===h&&(s||d.switchMeridian(),u=[a+1+r+1,a+1+r+3]),d.select(t,h,!0),o(u[0],u[1]),f.$digest()}};var T=d.init;d.init=function(){return u&&p.useNative?(t.prop("type","time"),void t.css("-webkit-appearance","textfield")):(c&&(t.prop("type","text"),t.attr("readonly","true"),t.on("click",l)),void T())};var C=d.destroy;d.destroy=function(){u&&p.useNative&&t.off("click",l),C()};var x=d.show;d.show=function(){x(),s(function(){d.$element.on(c?"touchstart":"mousedown",d.$onMouseDown),p.keyboard&&t.on("keydown",d.$onKeyDown)},0,!1)};var M=d.hide;return d.hide=function(e){d.$isShown&&(d.$element.off(c?"touchstart":"mousedown",d.$onMouseDown),p.keyboard&&t.off("keydown",d.$onKeyDown),M(e))},d}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","modelTimeFormat","useNative","hourStep","minuteStep","length","arrowBehavior","iconUp","iconDown"],function(e){angular.isDefined(n[e])&&(d[e]=n[e])}),n.bsShow&&e.$watch(n.bsShow,function(e){f&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(timepicker),?/i)),e===!0?f.show():f.hide())}),s&&(d.useNative||r.useNative)&&(d.timeFormat="HH:mm");var f=i(t,l,d);d=f.$options;var p=d.lang,m=function(e,t){return a.formatDate(e,t,p)},g=o({format:d.timeFormat,lang:p});angular.forEach(["minTime","maxTime"],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){f.$options[e]=g.getTimeForAttribute(e,t),!isNaN(f.$options[e])&&f.$build(),u(l.$dateValue)})}),e.$watch(n.ngModel,function(){f.update(l.$dateValue)},!0),l.$parsers.unshift(function(e){if(!e)return l.$setValidity("date",!0),null;var t=angular.isDate(e)?e:g.parse(e,l.$dateValue);return!t||isNaN(t.getTime())?void l.$setValidity("date",!1):(u(t),"string"===d.timeType?m(t,d.modelTimeFormat||d.timeFormat):"number"===d.timeType?l.$dateValue.getTime():"iso"===d.timeType?l.$dateValue.toISOString():new Date(l.$dateValue))}),l.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:"string"===d.timeType?g.parse(e,null,d.modelTimeFormat):new Date(e),l.$dateValue=t,c()}),l.$render=function(){t.val(c())},e.$on("$destroy",function(){f&&f.destroy(),d=null,f=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};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(t,n){function i(){V.$emit(F.prefixEvent+".show",E)}function r(){return V.$emit(F.prefixEvent+".hide",E),Y&&"focus"===F.trigger?t[0].blur():void M()}function s(){var e=F.trigger.split(" ");angular.forEach(e,function(e){"click"===e?t.on("click",E.toggle):"manual"!==e&&(t.on("hover"===e?"mouseenter":"focus",E.enter),t.on("hover"===e?"mouseleave":"blur",E.leave),"button"===A&&"hover"!==e&&t.on(v?"touchstart":"mousedown",E.$onFocusElementMouseDown))})}function p(){for(var e=F.trigger.split(" "),n=e.length;n--;){var a=e[n];"click"===a?t.off("click",E.toggle):"manual"!==a&&(t.off("hover"===a?"mouseenter":"focus",E.enter),t.off("hover"===a?"mouseleave":"blur",E.leave),"button"===A&&"hover"!==a&&t.off(v?"touchstart":"mousedown",E.$onFocusElementMouseDown))}}function b(){"focus"!==F.trigger?O.on("keyup",E.$onKeyUp):t.on("keyup",E.$onFocusKeyUp)}function D(){"focus"!==F.trigger?O.off("keyup",E.$onKeyUp):t.off("keyup",E.$onFocusKeyUp)}function k(){f(function(){O.on("click",T),w.on("click",E.hide),K=!0},0,!1)}function S(){K&&(O.off("click",T),w.off("click",E.hide),K=!1)}function T(e){e.stopPropagation()}function C(){return"body"===F.container?c.offset(F.target[0]||t[0]):c.position(F.target[0]||t[0])}function x(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":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 M(){clearTimeout(H),E.$isShown&&null!==O&&(F.autoClose&&S(),F.keyboard&&D()),q&&(q.$destroy(),q=null),O&&(O.remove(),O=E.$element=null)}var E={},A=t[0].nodeName.toLowerCase(),F=E.$options=angular.extend({},e,n);E.$promise=$(F.template);var V=E.$scope=F.scope&&F.scope.$new()||a.$new();if(F.delay&&angular.isString(F.delay)){var P=F.delay.split(",").map(parseFloat);F.delay=P.length>1?{show:P[0],hide:P[1]}:P[0]}F.title&&(V.title=u.trustAsHtml(F.title)),V.$setEnabled=function(e){V.$$postDigest(function(){E.setEnabled(e)})},V.$hide=function(){V.$$postDigest(function(){E.hide()})},V.$show=function(){V.$$postDigest(function(){E.show()})},V.$toggle=function(){V.$$postDigest(function(){E.toggle()})},E.$isShown=V.$isShown=!1;var H,I;F.contentTemplate&&(E.$promise=E.$promise.then(function(e){var t=angular.element(e);return $(F.contentTemplate).then(function(e){var n=g('[ng-bind="content"]',t[0]);return n.length||(n=g('[ng-bind="title"]',t[0])),n.removeAttr("ng-bind").html(e),t[0].outerHTML})}));var N,O,L,R,q;E.$promise.then(function(e){angular.isObject(e)&&(e=e.data),F.html&&(e=e.replace(y,'ng-bind-html="')),e=h.apply(e),L=e,N=o(e),E.init()}),E.init=function(){F.delay&&angular.isNumber(F.delay)&&(F.delay={show:F.delay,hide:F.delay}),"self"===F.container?R=t:angular.isElement(F.container)?R=F.container:F.container&&(R=g(F.container)),s(),F.target&&(F.target=angular.isElement(F.target)?F.target:g(F.target)),F.show&&V.$$postDigest(function(){"focus"===F.trigger?t[0].focus():E.show()})},E.destroy=function(){p(),M(),V.$destroy()},E.enter=function(){return clearTimeout(H),I="in",F.delay&&F.delay.show?void(H=setTimeout(function(){"in"===I&&E.show()},F.delay.show)):E.show()},E.show=function(){if(F.bsEnabled){V.$emit(F.prefixEvent+".show.before",E);var e,n;F.container?(e=R,n=R[0].lastChild?angular.element(R[0].lastChild):null):(e=null,n=t),O&&M(),q=E.$scope.$new(),O=E.$element=N(q,function(){}),O.css({top:"-9999px",left:"-9999px",display:"block",visibility:"hidden"}).addClass(F.placement),F.animation&&O.addClass(F.animation),F.type&&O.addClass(F.prefixClass+"-"+F.type),F.customClass&&O.addClass(F.customClass);var a=l.enter(O,e,n,i);a&&a.then&&a.then(i),E.$isShown=V.$isShown=!0,m(V),d(function(){E.$applyPlacement(),O&&O.css({visibility:"visible"})}),F.keyboard&&("focus"!==F.trigger&&E.focus(),b()),F.autoClose&&k()}},E.leave=function(){return clearTimeout(H),I="out",F.delay&&F.delay.hide?void(H=setTimeout(function(){"out"===I&&E.hide()},F.delay.hide)):E.hide()};var Y;E.hide=function(e){if(E.$isShown){V.$emit(F.prefixEvent+".hide.before",E),Y=e;var t=l.leave(O,r);t&&t.then&&t.then(r),E.$isShown=V.$isShown=!1,m(V),F.keyboard&&null!==O&&D(),F.autoClose&&null!==O&&S()}},E.toggle=function(){E.$isShown?E.leave():E.enter()},E.focus=function(){O[0].focus()},E.setEnabled=function(e){F.bsEnabled=e},E.$applyPlacement=function(){if(O){var e=C(),t=O.prop("offsetWidth"),n=O.prop("offsetHeight"),a=x(F.placement,e,t,n);a.top+="px",a.left+="px",O.css(a)}},E.$onKeyUp=function(e){27===e.which&&E.$isShown&&(E.hide(),e.stopPropagation())},E.$onFocusKeyUp=function(e){27===e.which&&(t[0].blur(),e.stopPropagation())},E.$onFocusElementMouseDown=function(e){e.preventDefault(),e.stopPropagation(),E.$isShown?t[0].blur():t[0].focus()};var K=!1;return E}function m(e){e.$$phase||e.$root&&e.$root.$$phase||e.$digest()}function g(e,n){return angular.element((n||t).querySelectorAll(e))}function $(e){return b[e]?b[e]:b[e]=i.when(r.get(e)||s.get(e)).then(function(t){return angular.isObject(t)?(r.put(e,t.data),t.data):t})}var h=String.prototype.trim,v="createTouch"in n.document,y=/ng-bind="/gi,w=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){var r={scope:e};angular.forEach(["template","contentTemplate","placement","container","target","delay","trigger","keyboard","html","animation","type","customClass"],function(e){angular.isDefined(i[e])&&(r[e]=i[e])}),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(){s&&s.$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(){s&&s.$applyPlacement()})},!0),i.bsShow&&e.$watch(i.bsShow,function(e){s&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(tooltip),?/i)),e===!0?s.show():s.hide())}),i.bsEnabled&&e.$watch(i.bsEnabled,function(e){s&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|1|,?(tooltip),?/i)),s.setEnabled(e===!1?!1:!0))});var s=a(t,r);e.$on("$destroy",function(){s&&s.destroy(),r=null,s=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,comparator:""};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=0},u.$resetMatches(),u.$activate=function(e){u.$$postDigest(function(){r.activate(e)})},u.$select=function(e){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=0)},r.activate=function(e){u.$activeIndex=e},r.select=function(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.$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()&&(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.$activeIndex0)return void s.$setViewValue(s.$viewValue.substring(0,s.$viewValue.length-1));e.length>c&&(e=e.slice(0,c));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=p.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)?p.displayValue(n):n,t.val(n?n.toString().replace(/<(?:.|\n)*?>/gm,"").trim():"")},e.$on("$destroy",function(){m&&m.destroy(),l=null,m=null})}}}])}(window,document);
//# sourceMappingURL=angular-strap.min.js.map
\ No newline at end of file
diff --git a/dist/angular-strap.min.js.map b/dist/angular-strap.min.js.map
old mode 100755
new mode 100644
index 456c6b727..8d3128be8
--- a/dist/angular-strap.min.js.map
+++ b/dist/angular-strap.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["module.js","affix/affix.js","alert/alert.js","aside/aside.js","button/button.js","collapse/collapse.js","datepicker/datepicker.js","dropdown/dropdown.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":[],"mappings":"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","file":"angular-strap.min.js","sourcesContent":["\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","'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 };\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 $affix.$parseOffsets();\n initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n setWidth = !element[0].style.width;\n\n // Bind events\n targetEl.on('scroll', $affix.checkPosition);\n targetEl.on('click', $affix.checkPositionWithEventLoop);\n windowEl.on('resize', $affix.$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 $affix.checkPosition();\n $affix.checkPositionWithEventLoop();\n\n };\n\n $affix.destroy = function() {\n\n // Unbind events\n targetEl.off('scroll', $affix.checkPosition);\n targetEl.off('click', $affix.checkPositionWithEventLoop);\n windowEl.off('resize', $affix.$debouncedOnResize);\n\n };\n\n $affix.checkPositionWithEventLoop = function() {\n\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 element.css('position', (options.offsetParent) ? '' : 'relative');\n if(setWidth) {\n element.css('width', '');\n }\n element.css('top', '');\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 element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n } else { // affix === 'middle'\n unpin = null;\n if(setWidth) {\n element.css('width', element[0].offsetWidth + 'px');\n }\n element.css('position', 'fixed');\n element.css('top', initialAffixTop + 'px');\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 element.css('position', (options.offsetParent) ? '' : 'relative');\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 element.css('position', initialPosition);\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, offsetTop: 'auto', target: affixTarget ? affixTarget.$element : angular.element($window)};\n angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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// ' ' +\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 // 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 // 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.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 = constantValueRegExp.test(attr.value) ? scope.$eval(attr.value) : attr.value;\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.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 };\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'], function (key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\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.$targets.$active = !self.$options.startCollapsed ? 0 : -1;\n self.$setActive = $scope.$setActive = function(value) {\n if(!self.$options.disallowToggle) {\n self.$targets.$active = self.$targets.$active === value ? -1 : value;\n } else {\n self.$targets.$active = value;\n }\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\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.$targets.$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 if (bsCollapseCtrl.$targets.$active !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\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 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 function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$targets.$active;\n $animate[index === active ? 'addClass' : 'removeClass'](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', ['mgcrea.ngStrap.helpers.dateParser', 'mgcrea.ngStrap.tooltip'])\n\n .provider('$datepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\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 modelDateFormat: null,\n dayFormat: 'dd',\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, $locale, dateFilter, 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 = $locale.id;\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 var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), viewDate.date + ((steps.day || 0) * value)));\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 $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $datepicker.$onKeyDown);\n }\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, $locale, dateFilter, $datepicker, $dateParser) {\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', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 // Initialize parser\n var dateParser = $dateParser({format: options.dateFormat, lang: options.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 // Null values should correctly reset the model value & validity\n if(!viewValue) {\n controller.$setValidity('date', true);\n return;\n }\n var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedDate || isNaN(parsedDate.getTime())) {\n controller.$setValidity('date', false);\n return;\n } else {\n validateAgainstMinMaxDate(parsedDate);\n }\n if(options.dateType === 'string') {\n return dateFilter(parsedDate, options.modelDateFormat || options.dateFormat);\n } else if(options.dateType === 'number') {\n return controller.$dateValue.getTime();\n } else if(options.dateType === 'iso') {\n return controller.$dateValue.toISOString();\n } else {\n return new Date(controller.$dateValue);\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 {\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 = date;\n return controller.$dateValue;\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(!controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : dateFilter(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($locale, $sce, dateFilter, $dateParser) {\n\n return function(picker) {\n\n var scope = picker.$scope;\n var options = picker.$options;\n var dateParser = $dateParser();\n\n var weekDaysMin = $locale.DATETIME_FORMATS.SHORTDAY;\n var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n var weekDaysLabelsHtml = $sce.trustAsHtml('' + weekDaysLabels.join(' ') + ' ');\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 var timezoneOffset = startDate.getTimezoneOffset() * 6e4;\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) {\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 = new Date().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 = new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i);\n days.push({date: day, isToday: day.toDateString() === today, label: dateFilter(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n }\n scope.title = dateFilter(firstDayOfMonth, 'MMMM yyyy');\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: 'MMM',\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: dateFilter(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n }\n scope.title = dateFilter(month, 'yyyy');\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: 'yyyy',\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: dateFilter(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 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) {\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 options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n bodyEl.on('click', onBodyClick);\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 // 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'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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.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 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 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 // 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\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('
');\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(scope.$isShown) return;\n\n if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n return;\n }\n var parent;\n if(angular.isElement(options.container)) {\n parent = options.container;\n } else {\n parent = options.container ? findElement(options.container) : null;\n }\n var after = options.container ? null : options.element;\n\n // Fetch a cloned element linked from template\n modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\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 scope.$isShown = true;\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\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 }\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(!scope.$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 scope.$isShown = false;\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n\n // Unbind events\n if(options.backdrop) {\n modalElement.off('click', hideOnBackdropClick);\n backdropElement.off('click', hideOnBackdropClick);\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 scope.$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 && scope.$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 return $modal;\n\n }\n\n // Helper functions\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n function fetchTemplate(template) {\n return $q.when($templateCache.get(template) || $http.get(template))\n .then(function(res) {\n if(angular.isObject(res)) {\n $templateCache.put(template, res.data);\n return res.data;\n }\n return res;\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'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 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', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'customClass', 'autoClose'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 // 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', debouncedCheckPosition);\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 setTimeout(this.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: ' ',\n placeholder: 'Choose among the following...',\n maxLength: 3,\n maxLengthHtml: 'selected',\n iconCheckmark: 'glyphicon glyphicon-ok'\n };\n\n this.$get = function($window, $document, $rootScope, $tooltip) {\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 scope.$activeIndex = 0;\n scope.$isMultiple = options.multiple;\n scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n scope.$iconCheckmark = options.iconCheckmark;\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 scope.$activeIndex.sort();\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);\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 // Select with enter\n if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n return $select.select(scope.$activeIndex);\n }\n\n // Navigate with keyboard\n 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 = $select.show;\n $select.show = function() {\n _show();\n if(options.multiple) {\n $select.$element.addClass('select-multiple');\n }\n $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $select.$onKeyDown);\n }\n };\n\n var _hide = $select.hide;\n $select.hide = function() {\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', 'multiple', 'allNoneButtons', 'maxLength', 'maxLengthHtml'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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(' ');\n inputEl.after(element);\n }\n\n // Build proper ngOptions\n var parsedOptions = $parseOptions(attr.ngOptions);\n\n // Initialize select\n var select = $select(element, controller, options);\n\n // Watch ngOptions values before filtering for changes\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n scope.$watch(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 }, true);\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) + defaults.caretHtml);\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 self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var activeIndex = self.$panes.$active;\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 self.$setActive(activeIndex);\n };\n\n self.$panes.$active = 0;\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\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) {\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 if(ngModelCtrl) {\n\n // Update the modelValue following\n bsTabsCtrl.$viewChangeListeners.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 * 1);\n return modelValue;\n });\n\n }\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 // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\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 var active = bsTabsCtrl.$panes.$active;\n $animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser', 'mgcrea.ngStrap.tooltip'])\n\n .provider('$timepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\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 modelTimeFormat: null,\n autoclose: false,\n minTime: -Infinity,\n maxTime: +Infinity,\n length: 5,\n hourStep: 1,\n minuteStep: 5,\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, $locale, dateFilter, $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 = $locale.id;\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 // View vars\n\n var selectedIndex = 0;\n var startDate = controller.$dateValue || new Date();\n var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n var format = $locale.DATETIME_FORMATS[options.timeFormat] || options.timeFormat;\n var formats = /(h+)([:\\.])?(m+)[ ]?(a?)/i.exec(format).slice(1);\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 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: dateFilter(hour, formats[0]), 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: dateFilter(minute, formats[2]), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n }\n\n var rows = [];\n for(i = 0; i < options.length; i++) {\n rows.push([hours[i], minutes[i]]);\n }\n scope.rows = rows;\n scope.showAM = !!formats[3];\n scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n scope.timeSeparator = formats[1];\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 }\n };\n\n $timepicker.$isDisabled = function(date, index) {\n var selectedTime;\n if(index === 0) {\n selectedTime = date.getTime() + viewDate.minute * 6e4;\n } else if(index === 1) {\n selectedTime = date.getTime() + viewDate.hour * 36e5;\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 = dateFilter(newDate, 'h').length;\n var minutes = newDate.getMinutes(), minutesLength = dateFilter(newDate, 'mm').length;\n if (index === 0) {\n newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n }\n else {\n newDate.setMinutes(minutes - (parseInt(options.minuteStep, 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);\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));\n angular.extend(viewDate, {minute: targetDate.getMinutes()});\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 = dateFilter(newDate, 'h').length;\n var minutes = newDate.getMinutes(), minutesLength = dateFilter(newDate, 'mm').length;\n var lateralMove = /(37|39)/.test(evt.keyCode);\n var count = 2 + !!formats[3] * 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 if(selectedIndex === 0) {\n if(evt.keyCode === 38) newDate.setHours(hours - parseInt(options.hourStep, 10));\n else if(evt.keyCode === 40) newDate.setHours(hours + parseInt(options.hourStep, 10));\n selectRange = [0, hoursLength];\n } else if(selectedIndex === 1) {\n if(evt.keyCode === 38) newDate.setMinutes(minutes - parseInt(options.minuteStep, 10));\n else if(evt.keyCode === 40) newDate.setMinutes(minutes + parseInt(options.minuteStep, 10));\n selectRange = [hoursLength + 1, hoursLength + 1 + minutesLength];\n } else if(selectedIndex === 2) {\n if(!lateralMove) $timepicker.switchMeridian();\n selectRange = [hoursLength + 1 + minutesLength + 1, hoursLength + 1 + minutesLength + 3];\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, end) {\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 $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $timepicker.$onKeyDown);\n }\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, $locale, dateFilter, $timepicker, $dateParser) {\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', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 // Initialize parser\n var dateParser = $dateParser({format: options.timeFormat, lang: options.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 // Null values should correctly reset the model value & validity\n if(!viewValue) {\n controller.$setValidity('date', true);\n return;\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;\n } else {\n validateAgainstMinMaxTime(parsedTime);\n }\n if(options.timeType === 'string') {\n return dateFilter(parsedTime, options.modelTimeFormat || options.timeFormat);\n } else if(options.timeType === 'number') {\n return controller.$dateValue.getTime();\n } else if(options.timeType === 'iso') {\n return controller.$dateValue.toISOString();\n } else {\n return new Date(controller.$dateValue);\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 {\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 = date;\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()) ? '' : dateFilter(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 };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, 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 // Support scope as string options\n if(options.title) {\n $tooltip.$scope.title = 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 $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 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 // 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 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 if(options.autoClose && $tooltip.$isShown && tipElement !== null) {\n $body.off('click');\n tipElement.off('click');\n }\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) return;\n\n scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n var parent = options.container ? tipContainer : null;\n var after = options.container ? null : element;\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', display: 'block', visibility: 'hidden'}).addClass(options.placement);\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 // 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\n $tooltip.$isShown = scope.$isShown = true;\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n $$rAF(function () {\n $tooltip.$applyPlacement();\n\n // Once placed, make the tooltip visible\n if(tipElement) tipElement.css({visibility: 'visible'});\n }); // var a = bodyEl.offsetWidth + 1; ?\n\n // Bind events\n if(options.keyboard) {\n if(options.trigger !== 'focus') {\n $tooltip.focus();\n tipElement.on('keyup', $tooltip.$onKeyUp);\n } else {\n element.on('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n if(options.autoClose) {\n // Stop propagation when clicking inside tooltip\n tipElement.on('click', function(event) {\n event.stopPropagation();\n });\n\n // Hide when clicking outside tooltip\n // use $timeout to setup this event, otherwise the \n // click on the element to show the popover will bubble \n // to the body and cause the popover to immediatly hide\n $timeout(function() {\n $body.on('click', function() {\n $tooltip.hide();\n });\n }, 0, false);\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 $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 // 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 scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n\n // Unbind events\n if(options.keyboard && tipElement !== null) {\n tipElement.off('keyup', $tooltip.$onKeyUp);\n }\n\n if(options.autoClose && tipElement !== null) {\n $body.off('click');\n tipElement.off('click');\n }\n\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\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 $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 // Protected methods\n\n $tooltip.$applyPlacement = function() {\n if(!tipElement) return;\n\n // Get the position of the tooltip element.\n var elementPosition = getPosition();\n\n // Get the height and width of the tooltip so we can center it.\n var tipWidth = tipElement.prop('offsetWidth'),\n tipHeight = tipElement.prop('offsetHeight');\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(options.placement, elementPosition, tipWidth, tipHeight);\n\n // Now set the calculated positioning.\n tipPosition.top += 'px';\n tipPosition.left += 'px';\n tipElement.css(tipPosition);\n\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 // Private methods\n\n function getPosition() {\n if(options.container === 'body') {\n return dimensions.offset(options.target[0] || element[0]);\n } else {\n return dimensions.position(options.target[0] || element[0]);\n }\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 destroyTipElement() {\n // Cancel pending callbacks\n clearTimeout(timeout);\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 findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n function fetchTemplate(template) {\n return $q.when($templateCache.get(template) || $http.get(template))\n .then(function(res) {\n if(angular.isObject(res)) {\n $templateCache.put(template, res.data);\n return res.data;\n }\n return res;\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', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'type', 'customClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 // 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 comparator: ''\n };\n\n this.$get = function($window, $rootScope, $tooltip) {\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 = 0;\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 = 0;\n }\n };\n\n $typeahead.activate = function(index) {\n scope.$activeIndex = index;\n };\n\n $typeahead.select = function(index) {\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);\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\n if($typeahead.$isVisible()) {\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 $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $typeahead.$onKeyDown);\n }\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 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', 'comparator'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Build proper ngOptions\n var filter = options.filter || defaults.filter;\n var limit = options.limit || defaults.limit;\n var comparator = options.comparator || defaults.comparator;\n\n var ngOptions = attr.ngOptions;\n if(filter) ngOptions += ' | ' + filter + ':$viewValue';\n if (comparator) ngOptions += ':' + comparator;\n if(limit) ngOptions += ' | limitTo:' + limit;\n var parsedOptions = $parseOptions(ngOptions);\n\n // Initialize typeahead\n var typeahead = $typeahead(element, controller, options);\n\n // Watch options on demand\n if(options.watchOptions) {\n // Watch ngOptions values before filtering for changes, drop function calls\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n scope.$watch(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 }, true);\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) ? selected.label : selected;\n element.val(selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '').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/"}
\ No newline at end of file
+{"version":3,"sources":["module.js","affix/affix.js","alert/alert.js","aside/aside.js","button/button.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":[],"mappings":"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","file":"angular-strap.min.js","sourcesContent":["\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","'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 };\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 element.css('position', (options.offsetParent) ? '' : 'relative');\n if(setWidth) {\n element.css('width', '');\n }\n element.css('top', '');\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 element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n } else { // affix === 'middle'\n unpin = null;\n if(setWidth) {\n element.css('width', element[0].offsetWidth + 'px');\n }\n element.css('position', 'fixed');\n element.css('top', initialAffixTop + 'px');\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 element.css('position', (options.offsetParent) ? '' : 'relative');\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 element.css('position', initialPosition);\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, offsetTop: 'auto', target: affixTarget ? affixTarget.$element : angular.element($window)};\n angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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// ' ' +\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 // 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 // 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.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 = constantValueRegExp.test(attr.value) ? scope.$eval(attr.value) : attr.value;\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.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 };\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'], function (key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\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.$targets.$active = !self.$options.startCollapsed ? 0 : -1;\n self.$setActive = $scope.$setActive = function(value) {\n if(!self.$options.disallowToggle) {\n self.$targets.$active = self.$targets.$active === value ? -1 : value;\n } else {\n self.$targets.$active = value;\n }\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\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.$targets.$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 if (bsCollapseCtrl.$targets.$active !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\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 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 function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$targets.$active;\n $animate[index === active ? 'addClass' : 'removeClass'](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 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 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 $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', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 // 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 if(options.dateType === 'string') {\n return formatDate(parsedDate, options.modelDateFormat || options.dateFormat);\n } else if(options.dateType === 'number') {\n return controller.$dateValue.getTime();\n } else if(options.dateType === 'iso') {\n return controller.$dateValue.toISOString();\n } else {\n return new Date(controller.$dateValue);\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 {\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 = date;\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('' + weekDaysLabels.join(' ') + ' ');\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 var timezoneOffset = startDate.getTimezoneOffset() * 6e4;\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) {\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 = new Date().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 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'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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+)[ ]?(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 a => :\n this.timeSeparator = function(timeFormat) {\n return splitTimeFormat(timeFormat)[1];\n };\n\n // h:mm a => true, H.mm => false\n this.showAM = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[3];\n };\n\n this.formatDate = function(date, format, lang){\n return dateFilter(date, format);\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 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 // 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 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 // 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\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('
');\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(scope.$isShown) return;\n\n if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n 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].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 // 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 }\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(!scope.$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 }\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 scope.$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 && scope.$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 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] = $q.when($templateCache.get(template) || $http.get(template))\n .then(function(res) {\n if(angular.isObject(res)) {\n $templateCache.put(template, res.data);\n return res.data;\n }\n return res;\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'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 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', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'customClass', 'autoClose'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 // 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', debouncedCheckPosition);\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: ' ',\n placeholder: 'Choose among the following...',\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 scope.$activeIndex = 0;\n scope.$isMultiple = options.multiple;\n scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n scope.$iconCheckmark = options.iconCheckmark;\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 scope.$activeIndex.sort();\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);\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 // Select with enter\n if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n return $select.select(scope.$activeIndex);\n }\n\n // Navigate with keyboard\n 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 = $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 $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', 'multiple', 'allNoneButtons', 'maxLength', 'maxLengthHtml'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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(' ');\n inputEl.after(element);\n }\n\n // Build proper ngOptions\n var parsedOptions = $parseOptions(attr.ngOptions);\n\n // Initialize select\n var select = $select(element, controller, options);\n\n // Watch ngOptions values before filtering for changes\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n scope.$watch(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 }, true);\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) + 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 // DEPRECATED: $viewChangeListeners, please use $activePaneChangeListeners\n // Because we deprecated ngModel usage, we rename viewChangeListeners to \n // activePaneChangeListeners to make more sense.\n self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var activeIndex = self.$panes.$active;\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 self.$setActive(activeIndex);\n };\n\n self.$panes.$active = 0;\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$activePaneChangeListeners.forEach(function(fn) {\n fn();\n });\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 // DEPRECATED: ngModel, please use bsActivePane\n // 'ngModel' is deprecated bacause if interferes with form validation\n // and status, so avoid using it here.\n if(ngModelCtrl) {\n console.warn('Usage of ngModel is deprecated, please use bsActivePane instead!');\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 * 1);\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 * 1);\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 // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\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 var active = bsTabsCtrl.$panes.$active;\n $animate[index === active ? '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 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 modelTimeFormat: null,\n autoclose: false,\n minTime: -Infinity,\n maxTime: +Infinity,\n length: 5,\n hourStep: 1,\n minuteStep: 5,\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) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n\n // View vars\n\n var selectedIndex = 0;\n var startDate = controller.$dateValue || new Date();\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 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 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\n var rows = [];\n for(i = 0; i < options.length; i++) {\n rows.push([hours[i], minutes[i]]);\n }\n scope.rows = rows;\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 }\n };\n\n $timepicker.$isDisabled = function(date, index) {\n var selectedTime;\n if(index === 0) {\n selectedTime = date.getTime() + viewDate.minute * 6e4;\n } else if(index === 1) {\n selectedTime = date.getTime() + viewDate.hour * 36e5;\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 if (index === 0) {\n newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n }\n else {\n newDate.setMinutes(minutes - (parseInt(options.minuteStep, 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);\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));\n angular.extend(viewDate, {minute: targetDate.getMinutes()});\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 lateralMove = /(37|39)/.test(evt.keyCode);\n var count = 2 + 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 if(selectedIndex === 0) {\n if(evt.keyCode === 38) newDate.setHours(hours - parseInt(options.hourStep, 10));\n else if(evt.keyCode === 40) newDate.setHours(hours + 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 if(evt.keyCode === 38) newDate.setMinutes(minutes - parseInt(options.minuteStep, 10));\n else if(evt.keyCode === 40) newDate.setMinutes(minutes + parseInt(options.minuteStep, 10));\n // re-calculate minutes length because we have changes minutes value\n minutesLength = formatDate(newDate, minutesFormat).length;\n selectRange = [hoursLength + 1, hoursLength + 1 + minutesLength];\n } else if(selectedIndex === 2) {\n if(!lateralMove) $timepicker.switchMeridian();\n selectRange = [hoursLength + 1 + minutesLength + 1, hoursLength + 1 + minutesLength + 3];\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, end) {\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', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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) {\n return $dateFormatter.formatDate(date, format, lang);\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 // 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 if(options.timeType === 'string') {\n return formatDate(parsedTime, options.modelTimeFormat || options.timeFormat);\n } else if(options.timeType === 'number') {\n return controller.$dateValue.getTime();\n } else if(options.timeType === 'iso') {\n return controller.$dateValue.toISOString();\n } else {\n return new Date(controller.$dateValue);\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 {\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 = date;\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 };\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 // 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 $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) 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', display: 'block', visibility: 'hidden'}).addClass(options.placement);\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 // 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\n $tooltip.$isShown = scope.$isShown = true;\n safeDigest(scope);\n $$rAF(function () {\n $tooltip.$applyPlacement();\n\n // Once placed, make the tooltip visible\n if(tipElement) tipElement.css({visibility: 'visible'});\n }); // var a = bodyEl.offsetWidth + 1; ?\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 $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 // 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 // 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 $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 // Protected methods\n\n $tooltip.$applyPlacement = function() {\n if(!tipElement) return;\n\n // Get the position of the tooltip element.\n var elementPosition = getPosition();\n\n // Get the height and width of the tooltip so we can center it.\n var tipWidth = tipElement.prop('offsetWidth'),\n tipHeight = tipElement.prop('offsetHeight');\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(options.placement, elementPosition, tipWidth, tipHeight);\n\n // Now set the calculated positioning.\n tipPosition.top += 'px';\n tipPosition.left += 'px';\n tipElement.css(tipPosition);\n\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() {\n if(options.container === 'body') {\n return dimensions.offset(options.target[0] || element[0]);\n } else {\n return dimensions.position(options.target[0] || element[0]);\n }\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 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] = $q.when($templateCache.get(template) || $http.get(template))\n .then(function(res) {\n if(angular.isObject(res)) {\n $templateCache.put(template, res.data);\n return res.data;\n }\n return res;\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', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'type', 'customClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 // 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 comparator: ''\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 = 0;\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 = 0;\n }\n };\n\n $typeahead.activate = function(index) {\n scope.$activeIndex = index;\n };\n\n $typeahead.select = function(index) {\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);\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\n if($typeahead.$isVisible()) {\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 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', 'comparator'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Build proper ngOptions\n var filter = options.filter || defaults.filter;\n var limit = options.limit || defaults.limit;\n var comparator = options.comparator || defaults.comparator;\n\n var ngOptions = attr.ngOptions;\n if(filter) ngOptions += ' | ' + filter + ':$viewValue';\n if (comparator) ngOptions += ':' + comparator;\n if(limit) ngOptions += ' | limitTo:' + limit;\n var parsedOptions = $parseOptions(ngOptions);\n\n // Initialize typeahead\n var typeahead = $typeahead(element, controller, options);\n\n // Watch options on demand\n if(options.watchOptions) {\n // Watch ngOptions values before filtering for changes, drop function calls\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n scope.$watch(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 }, true);\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 element.val(selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '').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/"}
\ No newline at end of file
diff --git a/dist/angular-strap.tpl.js b/dist/angular-strap.tpl.js
index 41c74eaec..2a99df860 100644
--- a/dist/angular-strap.tpl.js
+++ b/dist/angular-strap.tpl.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -8,17 +8,17 @@
(function(window, document, undefined) {
'use strict';
-// Source: aside.tpl.js
-angular.module('mgcrea.ngStrap.aside').run(['$templateCache', function($templateCache) {
+// Source: alert.tpl.js
+angular.module('mgcrea.ngStrap.alert').run(['$templateCache', function($templateCache) {
- $templateCache.put('aside/aside.tpl.html', '');
+ $templateCache.put('alert/alert.tpl.html', '×
');
}]);
-// Source: alert.tpl.js
-angular.module('mgcrea.ngStrap.alert').run(['$templateCache', function($templateCache) {
+// Source: aside.tpl.js
+angular.module('mgcrea.ngStrap.aside').run(['$templateCache', function($templateCache) {
- $templateCache.put('alert/alert.tpl.html', '×
');
+ $templateCache.put('aside/aside.tpl.html', '');
}]);
@@ -53,21 +53,21 @@ angular.module('mgcrea.ngStrap.popover').run(['$templateCache', function($templa
// Source: select.tpl.js
angular.module('mgcrea.ngStrap.select').run(['$templateCache', function($templateCache) {
- $templateCache.put('select/select.tpl.html', '');
+ $templateCache.put('select/select.tpl.html', '');
}]);
-// Source: timepicker.tpl.js
-angular.module('mgcrea.ngStrap.timepicker').run(['$templateCache', function($templateCache) {
+// Source: tab.tpl.js
+angular.module('mgcrea.ngStrap.tab').run(['$templateCache', function($templateCache) {
- $templateCache.put('timepicker/timepicker.tpl.html', '');
+ $templateCache.put('tab/tab.tpl.html', '
');
}]);
-// Source: tab.tpl.js
-angular.module('mgcrea.ngStrap.tab').run(['$templateCache', function($templateCache) {
+// Source: timepicker.tpl.js
+angular.module('mgcrea.ngStrap.timepicker').run(['$templateCache', function($templateCache) {
- $templateCache.put('tab/tab.tpl.html', '
');
+ $templateCache.put('timepicker/timepicker.tpl.html', '');
}]);
diff --git a/dist/angular-strap.tpl.min.js b/dist/angular-strap.tpl.min.js
index ef376d087..e83237633 100644
--- a/dist/angular-strap.tpl.min.js
+++ b/dist/angular-strap.tpl.min.js
@@ -1,8 +1,8 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-!function(){"use strict";angular.module("mgcrea.ngStrap.aside").run(["$templateCache",function(t){t.put("aside/aside.tpl.html",'')}]),angular.module("mgcrea.ngStrap.alert").run(["$templateCache",function(t){t.put("alert/alert.tpl.html",'×
')}]),angular.module("mgcrea.ngStrap.datepicker").run(["$templateCache",function(t){t.put("datepicker/datepicker.tpl.html",'')}]),angular.module("mgcrea.ngStrap.dropdown").run(["$templateCache",function(t){t.put("dropdown/dropdown.tpl.html",'')}]),angular.module("mgcrea.ngStrap.modal").run(["$templateCache",function(t){t.put("modal/modal.tpl.html",'')}]),angular.module("mgcrea.ngStrap.popover").run(["$templateCache",function(t){t.put("popover/popover.tpl.html",'')}]),angular.module("mgcrea.ngStrap.select").run(["$templateCache",function(t){t.put("select/select.tpl.html",'')}]),angular.module("mgcrea.ngStrap.timepicker").run(["$templateCache",function(t){t.put("timepicker/timepicker.tpl.html",'')}]),angular.module("mgcrea.ngStrap.tab").run(["$templateCache",function(t){t.put("tab/tab.tpl.html",'
')}]),angular.module("mgcrea.ngStrap.tooltip").run(["$templateCache",function(t){t.put("tooltip/tooltip.tpl.html",'')}]),angular.module("mgcrea.ngStrap.typeahead").run(["$templateCache",function(t){t.put("typeahead/typeahead.tpl.html",'')}])}(window,document);
\ No newline at end of file
+!function(){"use strict";angular.module("mgcrea.ngStrap.alert").run(["$templateCache",function(t){t.put("alert/alert.tpl.html",'×
')}]),angular.module("mgcrea.ngStrap.aside").run(["$templateCache",function(t){t.put("aside/aside.tpl.html",'')}]),angular.module("mgcrea.ngStrap.datepicker").run(["$templateCache",function(t){t.put("datepicker/datepicker.tpl.html",'')}]),angular.module("mgcrea.ngStrap.dropdown").run(["$templateCache",function(t){t.put("dropdown/dropdown.tpl.html",'')}]),angular.module("mgcrea.ngStrap.modal").run(["$templateCache",function(t){t.put("modal/modal.tpl.html",'')}]),angular.module("mgcrea.ngStrap.popover").run(["$templateCache",function(t){t.put("popover/popover.tpl.html",'')}]),angular.module("mgcrea.ngStrap.select").run(["$templateCache",function(t){t.put("select/select.tpl.html",'')}]),angular.module("mgcrea.ngStrap.tab").run(["$templateCache",function(t){t.put("tab/tab.tpl.html",'
')}]),angular.module("mgcrea.ngStrap.timepicker").run(["$templateCache",function(t){t.put("timepicker/timepicker.tpl.html",'')}]),angular.module("mgcrea.ngStrap.tooltip").run(["$templateCache",function(t){t.put("tooltip/tooltip.tpl.html",'')}]),angular.module("mgcrea.ngStrap.typeahead").run(["$templateCache",function(t){t.put("typeahead/typeahead.tpl.html",'')}])}(window,document);
\ No newline at end of file
diff --git a/dist/modules/affix.js b/dist/modules/affix.js
index 50ab9b03a..82e333620 100644
--- a/dist/modules/affix.js
+++ b/dist/modules/affix.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -53,33 +53,35 @@ angular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mg
$affix.init = function() {
- $affix.$parseOffsets();
+ this.$parseOffsets();
initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;
setWidth = !element[0].style.width;
// Bind events
- targetEl.on('scroll', $affix.checkPosition);
- targetEl.on('click', $affix.checkPositionWithEventLoop);
- windowEl.on('resize', $affix.$debouncedOnResize);
+ targetEl.on('scroll', this.checkPosition);
+ targetEl.on('click', this.checkPositionWithEventLoop);
+ windowEl.on('resize', this.$debouncedOnResize);
// Both of these checkPosition() calls are necessary for the case where
// the user hits refresh after scrolling to the bottom of the page.
- $affix.checkPosition();
- $affix.checkPositionWithEventLoop();
+ this.checkPosition();
+ this.checkPositionWithEventLoop();
};
$affix.destroy = function() {
// Unbind events
- targetEl.off('scroll', $affix.checkPosition);
- targetEl.off('click', $affix.checkPositionWithEventLoop);
- windowEl.off('resize', $affix.$debouncedOnResize);
+ targetEl.off('scroll', this.checkPosition);
+ targetEl.off('click', this.checkPositionWithEventLoop);
+ windowEl.off('resize', this.$debouncedOnResize);
};
$affix.checkPositionWithEventLoop = function() {
+ // IE 9 throws an error if we use 'this' instead of '$affix'
+ // in this setTimeout call
setTimeout($affix.checkPosition, 1);
};
diff --git a/dist/modules/affix.min.js b/dist/modules/affix.min.js
index a672df3ad..5a5cde978 100644
--- a/dist/modules/affix.min.js
+++ b/dist/modules/affix.min.js
@@ -1,9 +1,9 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";angular.module("mgcrea.ngStrap.affix",["mgcrea.ngStrap.helpers.dimensions","mgcrea.ngStrap.helpers.debounce"]).provider("$affix",function(){var t=this.defaults={offsetTop:"auto"};this.$get=["$window","debounce","dimensions",function(e,o,n){function f(f,r){function c(t,e,o){var n=a(),f=l();return $>=n?"top":null!==t&&n+t<=e.top?"middle":null!==v&&e.top+o+g>=f-v?"bottom":"middle"}function a(){return d[0]===e?e.pageYOffset:d[0].scrollTop}function l(){return d[0]===e?e.document.body.scrollHeight:d[0].scrollHeight}var u={},p=angular.extend({},t,r),d=p.target,h="affix affix-top affix-bottom",m=!1,g=0,P=0,$=0,v=0,T=null,x=null,b=f.parent();if(p.offsetParent)if(p.offsetParent.match(/^\d+$/))for(var k=0;k<1*p.offsetParent-1;k++)b=b.parent();else b=angular.element(p.offsetParent);return u.init=function(){u.$parseOffsets(),P=n.offset(f[0]).top+g,m=!f[0].style.width,d.on("scroll",u.checkPosition),d.on("click",u.checkPositionWithEventLoop),i.on("resize",u.$debouncedOnResize),u.checkPosition(),u.checkPositionWithEventLoop()},u.destroy=function(){d.off("scroll",u.checkPosition),d.off("click",u.checkPositionWithEventLoop),i.off("resize",u.$debouncedOnResize)},u.checkPositionWithEventLoop=function(){setTimeout(u.checkPosition,1)},u.checkPosition=function(){var t=a(),e=n.offset(f[0]),o=n.height(f[0]),i=c(x,e,o);T!==i&&(T=i,f.removeClass(h).addClass("affix"+("middle"!==i?"-"+i:"")),"top"===i?(x=null,f.css("position",p.offsetParent?"":"relative"),m&&f.css("width",""),f.css("top","")):"bottom"===i?(x=p.offsetUnpin?-(1*p.offsetUnpin):e.top-t,m&&f.css("width",""),f.css("position",p.offsetParent?"":"relative"),f.css("top",p.offsetParent?"":s[0].offsetHeight-v-o-P+"px")):(x=null,m&&f.css("width",f[0].offsetWidth+"px"),f.css("position","fixed"),f.css("top",g+"px")))},u.$onResize=function(){u.$parseOffsets(),u.checkPosition()},u.$debouncedOnResize=o(u.$onResize,50),u.$parseOffsets=function(){var t=f.css("position");f.css("position",p.offsetParent?"":"relative"),p.offsetTop&&("auto"===p.offsetTop&&(p.offsetTop="+0"),p.offsetTop.match(/^[-+]\d+$/)?(g=1*-p.offsetTop,$=p.offsetParent?n.offset(b[0]).top+1*p.offsetTop:n.offset(f[0]).top-n.css(f[0],"marginTop",!0)+1*p.offsetTop):$=1*p.offsetTop),p.offsetBottom&&(v=p.offsetParent&&p.offsetBottom.match(/^[-+]\d+$/)?l()-(n.offset(b[0]).top+n.height(b[0]))+1*p.offsetBottom+1:1*p.offsetBottom),f.css("position",t)},u.init(),u}var s=angular.element(e.document.body),i=angular.element(e);return f}]}).directive("bsAffix",["$affix","$window",function(t,e){return{restrict:"EAC",require:"^?bsAffixTarget",link:function(o,n,f,s){var i={scope:o,offsetTop:"auto",target:s?s.$element:angular.element(e)};angular.forEach(["offsetTop","offsetBottom","offsetParent","offsetUnpin"],function(t){angular.isDefined(f[t])&&(i[t]=f[t])});var r=t(n,i);o.$on("$destroy",function(){r&&r.destroy(),i=null,r=null})}}}]).directive("bsAffixTarget",function(){return{controller:["$element",function(t){this.$element=t}]}});
+"use strict";angular.module("mgcrea.ngStrap.affix",["mgcrea.ngStrap.helpers.dimensions","mgcrea.ngStrap.helpers.debounce"]).provider("$affix",function(){var t=this.defaults={offsetTop:"auto"};this.$get=["$window","debounce","dimensions",function(e,o,s){function n(n,r){function c(t,e,o){var s=a(),n=l();return $>=s?"top":null!==t&&s+t<=e.top?"middle":null!==v&&e.top+o+g>=n-v?"bottom":"middle"}function a(){return h[0]===e?e.pageYOffset:h[0].scrollTop}function l(){return h[0]===e?e.document.body.scrollHeight:h[0].scrollHeight}var u={},p=angular.extend({},t,r),h=p.target,d="affix affix-top affix-bottom",m=!1,g=0,P=0,$=0,v=0,T=null,x=null,b=n.parent();if(p.offsetParent)if(p.offsetParent.match(/^\d+$/))for(var k=0;k<1*p.offsetParent-1;k++)b=b.parent();else b=angular.element(p.offsetParent);return u.init=function(){this.$parseOffsets(),P=s.offset(n[0]).top+g,m=!n[0].style.width,h.on("scroll",this.checkPosition),h.on("click",this.checkPositionWithEventLoop),i.on("resize",this.$debouncedOnResize),this.checkPosition(),this.checkPositionWithEventLoop()},u.destroy=function(){h.off("scroll",this.checkPosition),h.off("click",this.checkPositionWithEventLoop),i.off("resize",this.$debouncedOnResize)},u.checkPositionWithEventLoop=function(){setTimeout(u.checkPosition,1)},u.checkPosition=function(){var t=a(),e=s.offset(n[0]),o=s.height(n[0]),i=c(x,e,o);T!==i&&(T=i,n.removeClass(d).addClass("affix"+("middle"!==i?"-"+i:"")),"top"===i?(x=null,n.css("position",p.offsetParent?"":"relative"),m&&n.css("width",""),n.css("top","")):"bottom"===i?(x=p.offsetUnpin?-(1*p.offsetUnpin):e.top-t,m&&n.css("width",""),n.css("position",p.offsetParent?"":"relative"),n.css("top",p.offsetParent?"":f[0].offsetHeight-v-o-P+"px")):(x=null,m&&n.css("width",n[0].offsetWidth+"px"),n.css("position","fixed"),n.css("top",g+"px")))},u.$onResize=function(){u.$parseOffsets(),u.checkPosition()},u.$debouncedOnResize=o(u.$onResize,50),u.$parseOffsets=function(){var t=n.css("position");n.css("position",p.offsetParent?"":"relative"),p.offsetTop&&("auto"===p.offsetTop&&(p.offsetTop="+0"),p.offsetTop.match(/^[-+]\d+$/)?(g=1*-p.offsetTop,$=p.offsetParent?s.offset(b[0]).top+1*p.offsetTop:s.offset(n[0]).top-s.css(n[0],"marginTop",!0)+1*p.offsetTop):$=1*p.offsetTop),p.offsetBottom&&(v=p.offsetParent&&p.offsetBottom.match(/^[-+]\d+$/)?l()-(s.offset(b[0]).top+s.height(b[0]))+1*p.offsetBottom+1:1*p.offsetBottom),n.css("position",t)},u.init(),u}var f=angular.element(e.document.body),i=angular.element(e);return n}]}).directive("bsAffix",["$affix","$window",function(t,e){return{restrict:"EAC",require:"^?bsAffixTarget",link:function(o,s,n,f){var i={scope:o,offsetTop:"auto",target:f?f.$element:angular.element(e)};angular.forEach(["offsetTop","offsetBottom","offsetParent","offsetUnpin"],function(t){angular.isDefined(n[t])&&(i[t]=n[t])});var r=t(s,i);o.$on("$destroy",function(){r&&r.destroy(),i=null,r=null})}}}]).directive("bsAffixTarget",function(){return{controller:["$element",function(t){this.$element=t}]}});
//# sourceMappingURL=affix.min.js.map
\ No newline at end of file
diff --git a/dist/modules/affix.min.js.map b/dist/modules/affix.min.js.map
old mode 100755
new mode 100644
index cc685f2f0..2d07b1380
--- a/dist/modules/affix.min.js.map
+++ b/dist/modules/affix.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["affix/affix.js"],"names":[],"mappings":"4JAaM,GAAA,KAAA,iCAIE,MAAA,UAAA,WAAA,aAAA,SAAA,EAAA,EAAA,2BAmKE,GAAA,EAAA,EAAA,GAEA,GAAA,GAAA,IACE,EAAA,UAEA,IAAA,EACF,2BAEF,kCAEA,SAEA,sBAMA,MAAA,GAAA,KAAA,EAAA,EAAA,YAAA,EAAA,GAAA,UAGF,QAAA,oEAjLE,GAAA,MAGI,EAAA,QAAA,UAAA,EAAA,GACA,EAAA,EAAA,OAGA,EAAA,oCAEJ,EAAA,EACA,EAAA,EACA,EAAA,EACE,EAAA,EACE,EAAA,OACE,KAEJ,EAAA,EAAA,YAEE,EAAA,aACF,GAAA,EAAA,aAAA,MAAA,SACF,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,aAAA,EAAA,qBAKE,GAAA,QAAA,QAAA,EAAA,uBAIA,KAAA,WAEA,EAAA,uCAEA,GAAA,EAAA,GAAA,MAAA,MAGA,EAAA,GAAA,SAAA,EAAA,0DAEF,EAAA,GAAA,SAAA,EAAA,oBAIE,EAAA,gBACA,EAAA,8BAIF,EAAA,QAAA,2CAIE,EAAA,IAAA,QAAA,EAAA,oEAKA,2BAAA,WAEA,WAAA,EAAA,cAAA,MAIA,cAAA,WAGA,GAAA,GAAA,IACA,EAAA,EAAA,OAAA,EAAA,IACA,EAAA,EAAA,OAAA,EAAA,IAGA,EAAA,EAAA,EAAA,EAAA,EAGE,KAAA,MACA,IAGA,YAAA,GAAA,SAAA,SAAA,WAAA,EAAA,IAAA,EAAA,KAEF,QAAA,GACE,EAAA,OACE,IAAA,WAAA,EAAA,aAAA,GAAA,YACF,GACA,EAAA,IAAA,QAAA,MAEE,IAAA,MAAA,KACA,WAAA,GAEF,EADA,EAAA,cACA,EAAA,EAAA,aAKF,EAAA,IAAA,EAEE,GACE,EAAA,IAAA,QAAA,IAEF,EAAA,IAAA,WAAA,EAAA,aAAA,GAAA,YACA,EAAA,IAAA,MAAA,EAAA,aAAA,GAAA,EAAA,GAAA,aAAA,EAAA,EAAA,EAAA,eAGJ,wCAGE,EAAA,IAAA,WAAA,SACA,EAAA,IAAA,MAAA,EAAA,WAKA,UAAA,WACA,EAAA,gBACA,EAAA,mBAEA,mBAAA,EAAA,EAAA,UAAA,MAEI,cAAA,cACF,GAAA,EAAA,IAAA,cAEE,IAAA,WAAA,EAAA,aAAA,GAAA,cAEE,YACF,SAAA,EAAA,YACA,EAAA,UAAA,MAEA,EAAA,UAAA,MAAA,cACF,EAAA,GAAA,EAAA,UAEE,EADF,EAAA,aACE,EAAA,OAAA,EAAA,IAAA,IAAA,EAAA,EAAA,uEAOA,EAAA,EAAA,EAAA,WAIF,EAAA,eAGF,EAFA,EAAA,cAAA,EAAA,aAAA,MAAA,aAEA,KAAA,EAAA,OAAA,EAAA,IAAA,IAAA,EAAA,OAAA,EAAA,KAAA,EAAA,EAAA,aAAA,oBAQA,EAAA,IAAA,WAAA,IA8BL,EAAA,YA1LG,GAAA,QAAA,QAAA,EAAA,SAAA,MACA,EAAA,QAAA,QAAA,0BAoMA,WAAA,SAAA,UAAA,SAAA,EAAA,mBAGA,qCAEA,SAAA,EAAA,EAAA,EAAA,MAEE,IAAA,MAAA,EAAA,UAAA,OAAA,OAAA,EAAA,EAAA,SAAA,QAAA,QAAA,YACA,SAAA,YAAA,eAAA,eAAA,eAAA,SAAA,GACA,QAAA,UAAA,EAAA,MAAA,EAAA,GAAA,EAAA,KAGJ,IAAA,GAAA,EAAA,EAAA,EACF,GAAA,IAAA,WAAA,0BAED,EAAA","file":"affix.min.js","sourcesContent":["'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 };\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 $affix.$parseOffsets();\n initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n setWidth = !element[0].style.width;\n\n // Bind events\n targetEl.on('scroll', $affix.checkPosition);\n targetEl.on('click', $affix.checkPositionWithEventLoop);\n windowEl.on('resize', $affix.$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 $affix.checkPosition();\n $affix.checkPositionWithEventLoop();\n\n };\n\n $affix.destroy = function() {\n\n // Unbind events\n targetEl.off('scroll', $affix.checkPosition);\n targetEl.off('click', $affix.checkPositionWithEventLoop);\n windowEl.off('resize', $affix.$debouncedOnResize);\n\n };\n\n $affix.checkPositionWithEventLoop = function() {\n\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 element.css('position', (options.offsetParent) ? '' : 'relative');\n if(setWidth) {\n element.css('width', '');\n }\n element.css('top', '');\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 element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n } else { // affix === 'middle'\n unpin = null;\n if(setWidth) {\n element.css('width', element[0].offsetWidth + 'px');\n }\n element.css('position', 'fixed');\n element.css('top', initialAffixTop + 'px');\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 element.css('position', (options.offsetParent) ? '' : 'relative');\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 element.css('position', initialPosition);\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, offsetTop: 'auto', target: affixTarget ? affixTarget.$element : angular.element($window)};\n angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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"],"sourceRoot":"/source/"}
\ No newline at end of file
+{"version":3,"sources":["affix/affix.js"],"names":[],"mappings":"4JAaM,GAAA,KAAA,iCAIE,MAAA,UAAA,WAAA,aAAA,SAAA,EAAA,EAAA,2BAqKE,GAAA,EAAA,EAAA,GAEA,GAAA,GAAA,IACE,EAAA,UAEA,IAAA,EACF,2BAEF,kCAEA,SAEA,sBAMA,MAAA,GAAA,KAAA,EAAA,EAAA,YAAA,EAAA,GAAA,UAGF,QAAA,oEAnLE,GAAA,MAGI,EAAA,QAAA,UAAA,EAAA,GACA,EAAA,EAAA,OAGA,EAAA,oCAEJ,EAAA,EACA,EAAA,EACA,EAAA,EACE,EAAA,EACE,EAAA,OACE,KAEJ,EAAA,EAAA,YAEE,EAAA,aACF,GAAA,EAAA,aAAA,MAAA,SACF,IAAA,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,aAAA,EAAA,qBAKE,GAAA,QAAA,QAAA,EAAA,uBAIA,KAAA,WAEA,KAAA,uCAEA,GAAA,EAAA,GAAA,MAAA,MAGA,EAAA,GAAA,SAAA,KAAA,6DAEF,EAAA,GAAA,SAAA,KAAA,oBAIE,KAAA,gBACA,KAAA,8BAIF,EAAA,QAAA,8CAIE,EAAA,IAAA,QAAA,KAAA,4BACA,EAAA,IAAA,SAAA,KAAA,6DAQA,WAAA,EAAA,cAAA,MAIA,cAAA,WAGA,GAAA,GAAA,IACA,EAAA,EAAA,OAAA,EAAA,IACA,EAAA,EAAA,OAAA,EAAA,IAGA,EAAA,EAAA,EAAA,EAAA,EAGE,KAAA,MACA,IAGA,YAAA,GAAA,SAAA,SAAA,WAAA,EAAA,IAAA,EAAA,KAEF,QAAA,GACE,EAAA,OACE,IAAA,WAAA,EAAA,aAAA,GAAA,YACF,GACA,EAAA,IAAA,QAAA,MAEE,IAAA,MAAA,KACA,WAAA,GAEF,EADA,EAAA,cACA,EAAA,EAAA,aAKF,EAAA,IAAA,EAEE,GACE,EAAA,IAAA,QAAA,IAEF,EAAA,IAAA,WAAA,EAAA,aAAA,GAAA,YACA,EAAA,IAAA,MAAA,EAAA,aAAA,GAAA,EAAA,GAAA,aAAA,EAAA,EAAA,EAAA,eAGJ,wCAGE,EAAA,IAAA,WAAA,SACA,EAAA,IAAA,MAAA,EAAA,WAKA,UAAA,WACA,EAAA,gBACA,EAAA,mBAEA,mBAAA,EAAA,EAAA,UAAA,MAEI,cAAA,cACF,GAAA,EAAA,IAAA,cAEE,IAAA,WAAA,EAAA,aAAA,GAAA,cAEE,YACF,SAAA,EAAA,YACA,EAAA,UAAA,MAEA,EAAA,UAAA,MAAA,cACF,EAAA,GAAA,EAAA,UAEE,EADF,EAAA,aACE,EAAA,OAAA,EAAA,IAAA,IAAA,EAAA,EAAA,uEAOA,EAAA,EAAA,EAAA,WAIF,EAAA,eAGF,EAFA,EAAA,cAAA,EAAA,aAAA,MAAA,aAEA,KAAA,EAAA,OAAA,EAAA,IAAA,IAAA,EAAA,OAAA,EAAA,KAAA,EAAA,EAAA,aAAA,oBAQA,EAAA,IAAA,WAAA,IA8BL,EAAA,YA5LG,GAAA,QAAA,QAAA,EAAA,SAAA,MACA,EAAA,QAAA,QAAA,0BAsMA,WAAA,SAAA,UAAA,SAAA,EAAA,mBAGA,qCAEA,SAAA,EAAA,EAAA,EAAA,MAEE,IAAA,MAAA,EAAA,UAAA,OAAA,OAAA,EAAA,EAAA,SAAA,QAAA,QAAA,YACA,SAAA,YAAA,eAAA,eAAA,eAAA,SAAA,GACA,QAAA,UAAA,EAAA,MAAA,EAAA,GAAA,EAAA,KAGJ,IAAA,GAAA,EAAA,EAAA,EACF,GAAA,IAAA,WAAA,0BAED,EAAA","file":"affix.min.js","sourcesContent":["'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 };\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 element.css('position', (options.offsetParent) ? '' : 'relative');\n if(setWidth) {\n element.css('width', '');\n }\n element.css('top', '');\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 element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n } else { // affix === 'middle'\n unpin = null;\n if(setWidth) {\n element.css('width', element[0].offsetWidth + 'px');\n }\n element.css('position', 'fixed');\n element.css('top', initialAffixTop + 'px');\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 element.css('position', (options.offsetParent) ? '' : 'relative');\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 element.css('position', initialPosition);\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, offsetTop: 'auto', target: affixTarget ? affixTarget.$element : angular.element($window)};\n angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/dist/modules/alert.js b/dist/modules/alert.js
index 829c94eb7..45fb66457 100644
--- a/dist/modules/alert.js
+++ b/dist/modules/alert.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/alert.min.js b/dist/modules/alert.min.js
index 689dc6920..ba317ddc0 100644
--- a/dist/modules/alert.min.js
+++ b/dist/modules/alert.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/alert.min.js.map b/dist/modules/alert.min.js.map
old mode 100755
new mode 100644
diff --git a/dist/modules/alert.tpl.js b/dist/modules/alert.tpl.js
index d1a503e5f..104879ed2 100644
--- a/dist/modules/alert.tpl.js
+++ b/dist/modules/alert.tpl.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/alert.tpl.min.js b/dist/modules/alert.tpl.min.js
index 4b481b86c..3dde478ab 100644
--- a/dist/modules/alert.tpl.min.js
+++ b/dist/modules/alert.tpl.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/aside.js b/dist/modules/aside.js
index fb72e3ec5..04cf5fd37 100644
--- a/dist/modules/aside.js
+++ b/dist/modules/aside.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/aside.min.js b/dist/modules/aside.min.js
index 528bee253..21211d6db 100644
--- a/dist/modules/aside.min.js
+++ b/dist/modules/aside.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/aside.min.js.map b/dist/modules/aside.min.js.map
old mode 100755
new mode 100644
diff --git a/dist/modules/aside.tpl.js b/dist/modules/aside.tpl.js
index adc9c5cff..bbc60549c 100644
--- a/dist/modules/aside.tpl.js
+++ b/dist/modules/aside.tpl.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/aside.tpl.min.js b/dist/modules/aside.tpl.min.js
index 57cce6757..664e53f24 100644
--- a/dist/modules/aside.tpl.min.js
+++ b/dist/modules/aside.tpl.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/button.js b/dist/modules/button.js
index 3f4603265..508641c3c 100644
--- a/dist/modules/button.js
+++ b/dist/modules/button.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/button.min.js b/dist/modules/button.min.js
index 75c2d5270..c33bfc7a4 100644
--- a/dist/modules/button.min.js
+++ b/dist/modules/button.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/button.min.js.map b/dist/modules/button.min.js.map
old mode 100755
new mode 100644
diff --git a/dist/modules/collapse.js b/dist/modules/collapse.js
index 9e47f6f8b..3754a01e4 100644
--- a/dist/modules/collapse.js
+++ b/dist/modules/collapse.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/collapse.min.js b/dist/modules/collapse.min.js
index d6fa18ce9..036f26811 100644
--- a/dist/modules/collapse.min.js
+++ b/dist/modules/collapse.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/collapse.min.js.map b/dist/modules/collapse.min.js.map
old mode 100755
new mode 100644
diff --git a/dist/modules/date-formatter.js b/dist/modules/date-formatter.js
new file mode 100644
index 000000000..7aa9d178f
--- /dev/null
+++ b/dist/modules/date-formatter.js
@@ -0,0 +1,61 @@
+/**
+ * angular-strap
+ * @version v2.1.4 - 2014-11-26
+ * @link http://mgcrea.github.io/angular-strap
+ * @author Olivier Louvignes (olivier@mg-crea.com)
+ * @license MIT License, http://www.opensource.org/licenses/MIT
+ */
+'use strict';
+
+angular.module('mgcrea.ngStrap.helpers.dateFormatter', [])
+
+ .service('$dateFormatter', ["$locale", "dateFilter", function($locale, dateFilter) {
+
+ // The unused `lang` arguments are on purpose. The default implementation does not
+ // use them and it always uses the locale loaded into the `$locale` service.
+ // Custom implementations might use it, thus allowing different directives to
+ // have different languages.
+
+ this.getDefaultLocale = function() {
+ return $locale.id;
+ };
+
+ // Format is either a data format name, e.g. "shortTime" or "fullDate", or a date format
+ // Return either the corresponding date format or the given date format.
+ this.getDatetimeFormat = function(format, lang) {
+ return $locale.DATETIME_FORMATS[format] || format;
+ };
+
+ this.weekdaysShort = function(lang) {
+ return $locale.DATETIME_FORMATS.SHORTDAY;
+ };
+
+ function splitTimeFormat(format) {
+ return /(h+)([:\.])?(m+)[ ]?(a?)/i.exec(format).slice(1);
+ }
+
+ // h:mm a => h
+ this.hoursFormat = function(timeFormat) {
+ return splitTimeFormat(timeFormat)[0];
+ };
+
+ // h:mm a => mm
+ this.minutesFormat = function(timeFormat) {
+ return splitTimeFormat(timeFormat)[2];
+ };
+
+ // h:mm a => :
+ this.timeSeparator = function(timeFormat) {
+ return splitTimeFormat(timeFormat)[1];
+ };
+
+ // h:mm a => true, H.mm => false
+ this.showAM = function(timeFormat) {
+ return !!splitTimeFormat(timeFormat)[3];
+ };
+
+ this.formatDate = function(date, format, lang){
+ return dateFilter(date, format);
+ };
+
+ }]);
diff --git a/dist/modules/date-formatter.min.js b/dist/modules/date-formatter.min.js
new file mode 100644
index 000000000..8484f9acd
--- /dev/null
+++ b/dist/modules/date-formatter.min.js
@@ -0,0 +1,9 @@
+/**
+ * angular-strap
+ * @version v2.1.4 - 2014-11-26
+ * @link http://mgcrea.github.io/angular-strap
+ * @author Olivier Louvignes (olivier@mg-crea.com)
+ * @license MIT License, http://www.opensource.org/licenses/MIT
+ */
+"use strict";angular.module("mgcrea.ngStrap.helpers.dateFormatter",[]).service("$dateFormatter",["$locale","dateFilter",function(t,e){function r(t){return/(h+)([:\.])?(m+)[ ]?(a?)/i.exec(t).slice(1)}this.getDefaultLocale=function(){return t.id},this.getDatetimeFormat=function(e){return t.DATETIME_FORMATS[e]||e},this.weekdaysShort=function(){return t.DATETIME_FORMATS.SHORTDAY},this.hoursFormat=function(t){return r(t)[0]},this.minutesFormat=function(t){return r(t)[2]},this.timeSeparator=function(t){return r(t)[1]},this.showAM=function(t){return!!r(t)[3]},this.formatDate=function(t,r){return e(t,r)}}]);
+//# sourceMappingURL=date-formatter.min.js.map
\ No newline at end of file
diff --git a/dist/modules/date-formatter.min.js.map b/dist/modules/date-formatter.min.js.map
new file mode 100644
index 000000000..2a191c2ca
--- /dev/null
+++ b/dist/modules/date-formatter.min.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["helpers/date-formatter.js"],"names":[],"mappings":"qBASI,OAAA,mDAEA,kBAAA,UAAA,aAAA,SAAA,EAAA,GAqBA,QAAA,GAAA,2DAdE,iBAAA,WACF,MAAA,GAAA,uCAMA,MAAA,GAAA,iBAAA,IAAA,iCAIA,MAAA,GAAA,iBAAA,UAQA,KAAA,YAAA,SAAA,mBAKA,KAAA,cAAA,SAAA,mBAKA,KAAA,cAAA,SAAA,2CAMD,QAAA,EAAA,GAAA","file":"date-formatter.min.js","sourcesContent":["'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+)[ ]?(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 a => :\n this.timeSeparator = function(timeFormat) {\n return splitTimeFormat(timeFormat)[1];\n };\n\n // h:mm a => true, H.mm => false\n this.showAM = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[3];\n };\n\n this.formatDate = function(date, format, lang){\n return dateFilter(date, format);\n };\n\n });\n"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/dist/modules/date-parser.js b/dist/modules/date-parser.js
index 7232b875f..e0f0bccd9 100644
--- a/dist/modules/date-parser.js
+++ b/dist/modules/date-parser.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -138,6 +138,8 @@ angular.module('mgcrea.ngStrap.helpers.dateParser', [])
};
$dateParser.parse = function(value, baseDate, format) {
+ // check for date format special names
+ if(format) format = $locale.DATETIME_FORMATS[format] || format;
if(angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format);
var formatRegex = format ? regExpForFormat(format) : regex;
var formatSetMap = format ? setMapForFormat(format) : setMap;
@@ -189,6 +191,23 @@ angular.module('mgcrea.ngStrap.helpers.dateParser', [])
return time;
};
+ /* Handle switch to/from daylight saving.
+ * Hours may be non-zero on daylight saving cut-over:
+ * > 12 when midnight changeover, but then cannot generate
+ * midnight datetime, so jump to 1AM, otherwise reset.
+ * @param date (Date) the date to check
+ * @return (Date) the corrected date
+ *
+ * __ copied from jquery ui datepicker __
+ */
+ $dateParser.daylightSavingAdjust = function(date) {
+ if (!date) {
+ return null;
+ }
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
+ return date;
+ };
+
// Private functions
function setMapForFormat(format) {
diff --git a/dist/modules/date-parser.min.js b/dist/modules/date-parser.min.js
index 74dd0461d..a70f0c97c 100644
--- a/dist/modules/date-parser.min.js
+++ b/dist/modules/date-parser.min.js
@@ -1,9 +1,9 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";angular.module("mgcrea.ngStrap.helpers.dateParser",[]).provider("$dateParser",["$localeProvider",function(){function t(){this.year=1970,this.month=0,this.day=1,this.hours=0,this.minutes=0,this.seconds=0,this.milliseconds=0}function e(){}function s(t){return!isNaN(parseFloat(t))&&isFinite(t)}function n(t,e){for(var s=t.length,n=e.toString().toLowerCase(),r=0;s>r;r++)if(t[r].toLowerCase()===n)return r;return-1}t.prototype.setMilliseconds=function(t){this.milliseconds=t},t.prototype.setSeconds=function(t){this.seconds=t},t.prototype.setMinutes=function(t){this.minutes=t},t.prototype.setHours=function(t){this.hours=t},t.prototype.getHours=function(){return this.hours},t.prototype.setDate=function(t){this.day=t},t.prototype.setMonth=function(t){this.month=t},t.prototype.setFullYear=function(t){this.year=t},t.prototype.fromDate=function(t){return this.year=t.getFullYear(),this.month=t.getMonth(),this.day=t.getDate(),this.hours=t.getHours(),this.minutes=t.getMinutes(),this.seconds=t.getSeconds(),this.milliseconds=t.getMilliseconds(),this},t.prototype.toDate=function(){return new Date(this.year,this.month,this.day,this.hours,this.minutes,this.seconds,this.milliseconds)};var r=t.prototype,i=this.defaults={format:"shortDate",strict:!1};this.$get=["$locale","dateFilter",function(o,a){var u=function(u){function h(t){var e,s=Object.keys(y),n=[],r=[],i=t;for(e=0;e1){var o=i.search(s[e]);t=t.split(s[e]).join(""),y[s[e]]&&(n[o]=y[s[e]])}return angular.forEach(n,function(t){t&&r.push(t)}),r}function c(t){return t.replace(/\//g,"[\\/]").replace("/-/g","[-]").replace(/\./g,"[.]").replace(/\\s/g,"[\\s]")}function l(t){var e,s=Object.keys(p),n=t;for(e=0;er;r++)if(t[r].toLowerCase()===n)return r;return-1}t.prototype.setMilliseconds=function(t){this.milliseconds=t},t.prototype.setSeconds=function(t){this.seconds=t},t.prototype.setMinutes=function(t){this.minutes=t},t.prototype.setHours=function(t){this.hours=t},t.prototype.getHours=function(){return this.hours},t.prototype.setDate=function(t){this.day=t},t.prototype.setMonth=function(t){this.month=t},t.prototype.setFullYear=function(t){this.year=t},t.prototype.fromDate=function(t){return this.year=t.getFullYear(),this.month=t.getMonth(),this.day=t.getDate(),this.hours=t.getHours(),this.minutes=t.getMinutes(),this.seconds=t.getSeconds(),this.milliseconds=t.getMilliseconds(),this},t.prototype.toDate=function(){return new Date(this.year,this.month,this.day,this.hours,this.minutes,this.seconds,this.milliseconds)};var r=t.prototype,i=this.defaults={format:"shortDate",strict:!1};this.$get=["$locale","dateFilter",function(o,a){var u=function(u){function h(t){var e,s=Object.keys(d),n=[],r=[],i=t;for(e=0;e1){var o=i.search(s[e]);t=t.split(s[e]).join(""),d[s[e]]&&(n[o]=d[s[e]])}return angular.forEach(n,function(t){t&&r.push(t)}),r}function l(t){return t.replace(/\//g,"[\\/]").replace("/-/g","[-]").replace(/\./g,"[.]").replace(/\\s/g,"[\\s]")}function c(t){var e,s=Object.keys(p),n=t;for(e=0;e12?t.getHours()+2:0),t):null},m.init(),m};return u}]}]);
//# sourceMappingURL=date-parser.min.js.map
\ No newline at end of file
diff --git a/dist/modules/date-parser.min.js.map b/dist/modules/date-parser.min.js.map
old mode 100755
new mode 100644
index 68ca30c9e..bfb18392c
--- a/dist/modules/date-parser.min.js.map
+++ b/dist/modules/date-parser.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["helpers/date-parser.js"],"names":[],"mappings":"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","file":"date-parser.min.js","sourcesContent":["'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 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"],"sourceRoot":"/source/"}
\ No newline at end of file
+{"version":3,"sources":["helpers/date-parser.js"],"names":[],"mappings":"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","file":"date-parser.min.js","sourcesContent":["'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 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 // 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"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/dist/modules/datepicker.js b/dist/modules/datepicker.js
index 70707243d..451469ef5 100644
--- a/dist/modules/datepicker.js
+++ b/dist/modules/datepicker.js
@@ -1,13 +1,16 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
'use strict';
-angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser', 'mgcrea.ngStrap.tooltip'])
+angular.module('mgcrea.ngStrap.datepicker', [
+ 'mgcrea.ngStrap.helpers.dateParser',
+ 'mgcrea.ngStrap.helpers.dateFormatter',
+ 'mgcrea.ngStrap.tooltip'])
.provider('$datepicker', function() {
@@ -27,6 +30,10 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
dateFormat: 'shortDate',
modelDateFormat: null,
dayFormat: 'dd',
+ monthFormat: 'MMM',
+ yearFormat: 'yyyy',
+ monthTitleFormat: 'MMMM yyyy',
+ yearTitleFormat: 'yyyy',
strictFormat: false,
autoclose: false,
minDate: -Infinity,
@@ -39,12 +46,12 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
iconRight: 'glyphicon glyphicon-chevron-right'
};
- this.$get = ["$window", "$document", "$rootScope", "$sce", "$locale", "dateFilter", "datepickerViews", "$tooltip", "$timeout", function($window, $document, $rootScope, $sce, $locale, dateFilter, datepickerViews, $tooltip, $timeout) {
+ this.$get = ["$window", "$document", "$rootScope", "$sce", "$dateFormatter", "datepickerViews", "$tooltip", "$timeout", function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {
var bodyEl = angular.element($window.document.body);
var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
var isTouch = ('createTouch' in $window.document) && isNative;
- if(!defaults.lang) defaults.lang = $locale.id;
+ if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();
function DatepickerFactory(element, controller, config) {
@@ -143,7 +150,10 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
$datepicker.$selectPane = function(value) {
var steps = $picker.steps;
- var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), viewDate.date + ((steps.day || 0) * value)));
+ // set targetDate to first day of month to avoid problems with
+ // date values rollover. This assumes the viewDate does not
+ // depend on the day of the month
+ var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));
angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});
$datepicker.$build();
};
@@ -217,10 +227,14 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
var _show = $datepicker.show;
$datepicker.show = function() {
_show();
- $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);
- if(options.keyboard) {
- element.on('keydown', $datepicker.$onKeyDown);
- }
+ // use timeout to hookup the events to prevent
+ // event bubbling from being processed imediately.
+ $timeout(function() {
+ $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);
+ if(options.keyboard) {
+ element.on('keydown', $datepicker.$onKeyDown);
+ }
+ }, 0, false);
};
var _hide = $datepicker.hide;
@@ -244,7 +258,7 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
})
- .directive('bsDatepicker', ["$window", "$parse", "$q", "$locale", "dateFilter", "$datepicker", "$dateParser", function($window, $parse, $q, $locale, dateFilter, $datepicker, $dateParser) {
+ .directive('bsDatepicker', ["$window", "$parse", "$q", "$dateFormatter", "$dateParser", "$datepicker", function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {
var defaults = $datepicker.defaults;
var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
@@ -273,8 +287,13 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
// Set expected iOS format
if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';
- // Initialize parser
- var dateParser = $dateParser({format: options.dateFormat, lang: options.lang, strict: options.strictFormat});
+ var lang = options.lang;
+
+ var formatDate = function(date, format) {
+ return $dateFormatter.formatDate(date, format, lang);
+ };
+
+ var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});
// Observe attributes for changes
angular.forEach(['minDate', 'maxDate'], function(key) {
@@ -329,17 +348,22 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
// Null values should correctly reset the model value & validity
if(!viewValue) {
controller.$setValidity('date', true);
- return;
+ // BREAKING CHANGE:
+ // return null (not undefined) when input value is empty, so angularjs 1.3
+ // ngModelController can go ahead and run validators, like ngRequired
+ return null;
}
var parsedDate = dateParser.parse(viewValue, controller.$dateValue);
if(!parsedDate || isNaN(parsedDate.getTime())) {
controller.$setValidity('date', false);
+ // return undefined, causes ngModelController to
+ // invalidate model value
return;
} else {
validateAgainstMinMaxDate(parsedDate);
}
if(options.dateType === 'string') {
- return dateFilter(parsedDate, options.modelDateFormat || options.dateFormat);
+ return formatDate(parsedDate, options.modelDateFormat || options.dateFormat);
} else if(options.dateType === 'number') {
return controller.$dateValue.getTime();
} else if(options.dateType === 'iso') {
@@ -368,15 +392,19 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
// date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);
// }
controller.$dateValue = date;
- return controller.$dateValue;
+ return getDateFormattedString();
});
// viewValue -> element
controller.$render = function() {
// console.warn('$render("%s"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);
- element.val(!controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : dateFilter(controller.$dateValue, options.dateFormat));
+ element.val(getDateFormattedString());
};
+ function getDateFormattedString() {
+ return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);
+ }
+
// Garbage collection
scope.$on('$destroy', function() {
if(datepicker) datepicker.destroy();
@@ -410,15 +438,20 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
return ((n % m) + m) % m;
}
- this.$get = ["$locale", "$sce", "dateFilter", "$dateParser", function($locale, $sce, dateFilter, $dateParser) {
+ this.$get = ["$dateFormatter", "$dateParser", "$sce", function($dateFormatter, $dateParser, $sce) {
return function(picker) {
var scope = picker.$scope;
var options = picker.$options;
- var dateParser = $dateParser();
- var weekDaysMin = $locale.DATETIME_FORMATS.SHORTDAY;
+ var lang = options.lang;
+ var formatDate = function(date, format) {
+ return $dateFormatter.formatDate(date, format, lang);
+ };
+ var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});
+
+ var weekDaysMin = $dateFormatter.weekdaysShort(lang);
var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));
var weekDaysLabelsHtml = $sce.trustAsHtml('' + weekDaysLabels.join(' ') + ' ');
@@ -447,10 +480,10 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);
var days = [], day;
for(var i = 0; i < 42; i++) { // < 7 * 6
- day = new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i);
- days.push({date: day, isToday: day.toDateString() === today, label: dateFilter(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});
+ day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));
+ 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)});
}
- scope.title = dateFilter(firstDayOfMonth, 'MMMM yyyy');
+ scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);
scope.showLabels = true;
scope.labels = weekDaysLabelsHtml;
scope.rows = split(days, this.split);
@@ -495,7 +528,7 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
}
}, {
name: 'month',
- format: 'MMM',
+ format: options.monthFormat,
split: 4,
steps: { year: 1 },
update: function(date, force) {
@@ -512,9 +545,9 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
var months = [], month;
for (var i = 0; i < 12; i++) {
month = new Date(viewDate.year, i, 1);
- months.push({date: month, label: dateFilter(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});
+ months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});
}
- scope.title = dateFilter(month, 'yyyy');
+ scope.title = formatDate(month, options.yearTitleFormat);
scope.showLabels = false;
scope.rows = split(months, this.split);
this.built = true;
@@ -542,7 +575,7 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
}
}, {
name: 'year',
- format: 'yyyy',
+ format: options.yearFormat,
split: 4,
steps: { year: 12 },
update: function(date, force) {
@@ -559,7 +592,7 @@ angular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser'
var years = [], year;
for (var i = 0; i < 12; i++) {
year = new Date(firstYear + i, 0, 1);
- years.push({date: year, label: dateFilter(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});
+ years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});
}
scope.title = years[0].label + '-' + years[years.length - 1].label;
scope.showLabels = false;
diff --git a/dist/modules/datepicker.min.js b/dist/modules/datepicker.min.js
index 1dec51586..e512c3187 100644
--- a/dist/modules/datepicker.min.js
+++ b/dist/modules/datepicker.min.js
@@ -1,9 +1,9 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";angular.module("mgcrea.ngStrap.datepicker",["mgcrea.ngStrap.helpers.dateParser","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",modelDateFormat:null,dayFormat:"dd",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","$locale","dateFilter","datepickerViews","$tooltip","$timeout",function(t,a,n,i,o,r,d,l,s){function u(t,a,n){function i(e){e.selected=r.$isSelected(e.date)}function o(){t[0].focus()}var r=l(t,angular.extend({},e,n)),u=n.scope,$=r.$options,f=r.$scope;$.startView&&($.startView-=$.minView);var h=d(r);r.$views=h.views;var m=h.viewDate;f.$mode=$.startView,f.$iconLeft=$.iconLeft,f.$iconRight=$.iconRight;var D=r.$views[f.$mode];f.$select=function(e){r.select(e)},f.$selectPane=function(e){r.$selectPane(e)},f.$toggleMode=function(){r.setMode((f.$mode+1)%r.$views.length)},r.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())&&(r.$date=e,D.update.call(D,e)),r.$build(!0)},r.updateDisabledDates=function(e){$.disabledDateRanges=e;for(var t=0,a=f.rows.length;a>t;t++)angular.forEach(f.rows[t],r.$setDisabledEl)},r.select=function(e,t){angular.isDate(a.$dateValue)||(a.$dateValue=new Date(e)),!f.$mode||t?(a.$setViewValue(angular.copy(e)),a.$render(),$.autoclose&&!t&&s(function(){r.hide(!0)})):(angular.extend(m,{year:e.getFullYear(),month:e.getMonth(),date:e.getDate()}),r.setMode(f.$mode-1),r.$build())},r.setMode=function(e){f.$mode=e,D=r.$views[f.$mode],r.$build()},r.$build=function(e){e===!0&&D.built||(e!==!1||D.built)&&D.build.call(D)},r.$updateSelected=function(){for(var e=0,t=f.rows.length;t>e;e++)angular.forEach(f.rows[e],i)},r.$isSelected=function(e){return D.isSelected(e)},r.$setDisabledEl=function(e){e.disabled=D.isDisabled(e.date)},r.$selectPane=function(e){var t=D.steps,a=new Date(Date.UTC(m.year+(t.year||0)*e,m.month+(t.month||0)*e,m.date+(t.day||0)*e));angular.extend(m,{year:a.getUTCFullYear(),month:a.getUTCMonth(),date:a.getUTCDate()}),r.$build()},r.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),g){var t=angular.element(e.target);"button"!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler("click")}},r.$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.$mode?f.$apply(function(){r.setMode(f.$mode-1)}):r.hide(!0);D.onKeyDown(e),u.$digest()}};var p=r.init;r.init=function(){return c&&$.useNative?(t.prop("type","date"),void t.css("-webkit-appearance","textfield")):(g&&(t.prop("type","text"),t.attr("readonly","true"),t.on("click",o)),void p())};var y=r.destroy;r.destroy=function(){c&&$.useNative&&t.off("click",o),y()};var w=r.show;r.show=function(){w(),r.$element.on(g?"touchstart":"mousedown",r.$onMouseDown),$.keyboard&&t.on("keydown",r.$onKeyDown)};var b=r.hide;return r.hide=function(e){r.$isShown&&(r.$element.off(g?"touchstart":"mousedown",r.$onMouseDown),$.keyboard&&t.off("keydown",r.$onKeyDown),b(e))},r}var c=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),g="createTouch"in t.document&&c;return e.lang||(e.lang=o.id),u.defaults=e,u}]}).directive("bsDatepicker",["$window","$parse","$q","$locale","dateFilter","$datepicker","$dateParser",function(e,t,a,n,i,o,r){var d=(o.defaults,/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent));return{restrict:"EAC",require:"ngModel",link:function(e,t,a,n){function l(e){return e&&e.length?e:null}function s(e){if(angular.isDate(e)){var t=isNaN(c.$options.minDate)||e.getTime()>=c.$options.minDate,a=isNaN(c.$options.maxDate)||e.getTime()<=c.$options.maxDate,i=t&&a;n.$setValidity("date",i),n.$setValidity("min",t),n.$setValidity("max",a),i&&(n.$dateValue=e)}}var u={scope:e,controller:n};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","autoclose","dateType","dateFormat","modelDateFormat","dayFormat","strictFormat","startWeek","startDate","useNative","lang","startView","minView","iconLeft","iconRight","daysOfWeekDisabled"],function(e){angular.isDefined(a[e])&&(u[e]=a[e])}),a.bsShow&&e.$watch(a.bsShow,function(e){c&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(datepicker),?/i)),e===!0?c.show():c.hide())});var c=o(t,n,u);u=c.$options,d&&u.useNative&&(u.dateFormat="yyyy-MM-dd");var g=r({format:u.dateFormat,lang:u.lang,strict:u.strictFormat});angular.forEach(["minDate","maxDate"],function(e){angular.isDefined(a[e])&&a.$observe(e,function(t){c.$options[e]=g.getDateForAttribute(e,t),!isNaN(c.$options[e])&&c.$build(!1),s(n.$dateValue)})}),e.$watch(a.ngModel,function(){c.update(n.$dateValue)},!0),angular.isDefined(a.disabledDates)&&e.$watch(a.disabledDates,function(e,t){e=l(e),t=l(t),e&&c.updateDisabledDates(e)}),n.$parsers.unshift(function(e){if(!e)return void n.$setValidity("date",!0);var t=g.parse(e,n.$dateValue);return!t||isNaN(t.getTime())?void n.$setValidity("date",!1):(s(t),"string"===u.dateType?i(t,u.modelDateFormat||u.dateFormat):"number"===u.dateType?n.$dateValue.getTime():"iso"===u.dateType?n.$dateValue.toISOString():new Date(n.$dateValue))}),n.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:"string"===u.dateType?g.parse(e,null,u.modelDateFormat):new Date(e),n.$dateValue=t,n.$dateValue}),n.$render=function(){t.val(!n.$dateValue||isNaN(n.$dateValue.getTime())?"":i(n.$dateValue,u.dateFormat))},e.$on("$destroy",function(){c&&c.destroy(),u=null,c=null})}}}]).provider("datepickerViews",function(){function e(e,t){for(var a=[];e.length>0;)a.push(e.splice(0,t));return a}function t(e,t){return(e%t+t)%t}this.defaults={dayFormat:"dd",daySplit:7};this.$get=["$locale","$sce","dateFilter","$dateParser",function(a,n,i,o){return function(r){var d=r.$scope,l=r.$options,s=o(),u=a.DATETIME_FORMATS.SHORTDAY,c=u.slice(l.startWeek).concat(u.slice(0,l.startWeek)),g=n.trustAsHtml(''+c.join(' ')+" "),$=r.$date||(l.startDate?s.getDateForAttribute("startDate",l.startDate):new Date),f={year:$.getFullYear(),month:$.getMonth(),date:$.getDate()},h=(6e4*$.getTimezoneOffset(),[{format:l.dayFormat,split:7,steps:{month:1},update:function(e,t){!this.built||t||e.getFullYear()!==f.year||e.getMonth()!==f.month?(angular.extend(f,{year:r.$date.getFullYear(),month:r.$date.getMonth(),date:r.$date.getDate()}),r.$build()):e.getDate()!==f.date&&(f.date=r.$date.getDate(),r.$updateSelected())},build:function(){var a=new Date(f.year,f.month,1),n=a.getTimezoneOffset(),o=new Date(+a-864e5*t(a.getDay()-l.startWeek,7)),s=o.getTimezoneOffset(),u=(new Date).toDateString();s!==n&&(o=new Date(+o+6e4*(s-n)));for(var c,$=[],h=0;42>h;h++)c=new Date(o.getFullYear(),o.getMonth(),o.getDate()+h),$.push({date:c,isToday:c.toDateString()===u,label:i(c,this.format),selected:r.$date&&this.isSelected(c),muted:c.getMonth()!==f.month,disabled:this.isDisabled(c)});d.title=i(a,"MMMM yyyy"),d.showLabels=!0,d.labels=g,d.rows=e($,this.split),this.built=!0},isSelected:function(e){return r.$date&&e.getFullYear()===r.$date.getFullYear()&&e.getMonth()===r.$date.getMonth()&&e.getDate()===r.$date.getDate()},isDisabled:function(e){var t=e.getTime();if(tl.maxDate)return!0;if(-1!==l.daysOfWeekDisabled.indexOf(e.getDay()))return!0;if(l.disabledDateRanges)for(var a=0;a=l.disabledDateRanges[a].start&&t<=l.disabledDateRanges[a].end)return!0;return!1},onKeyDown:function(e){if(r.$date){var t,a=r.$date.getTime();37===e.keyCode?t=new Date(a-864e5):38===e.keyCode?t=new Date(a-6048e5):39===e.keyCode?t=new Date(a+864e5):40===e.keyCode&&(t=new Date(a+6048e5)),this.isDisabled(t)||r.select(t,!0)}}},{name:"month",format:"MMM",split:4,steps:{year:1},update:function(e){this.built&&e.getFullYear()===f.year?e.getMonth()!==f.month&&(angular.extend(f,{month:r.$date.getMonth(),date:r.$date.getDate()}),r.$updateSelected()):(angular.extend(f,{year:r.$date.getFullYear(),month:r.$date.getMonth(),date:r.$date.getDate()}),r.$build())},build:function(){for(var t,a=(new Date(f.year,0,1),[]),n=0;12>n;n++)t=new Date(f.year,n,1),a.push({date:t,label:i(t,this.format),selected:r.$isSelected(t),disabled:this.isDisabled(t)});d.title=i(t,"yyyy"),d.showLabels=!1,d.rows=e(a,this.split),this.built=!0},isSelected:function(e){return r.$date&&e.getFullYear()===r.$date.getFullYear()&&e.getMonth()===r.$date.getMonth()},isDisabled:function(e){var t=+new Date(e.getFullYear(),e.getMonth()+1,0);return tl.maxDate},onKeyDown:function(e){if(r.$date){var t=r.$date.getMonth(),a=new Date(r.$date);37===e.keyCode?a.setMonth(t-1):38===e.keyCode?a.setMonth(t-4):39===e.keyCode?a.setMonth(t+1):40===e.keyCode&&a.setMonth(t+4),this.isDisabled(a)||r.select(a,!0)}}},{name:"year",format:"yyyy",split:4,steps:{year:12},update:function(e,t){!this.built||t||parseInt(e.getFullYear()/20,10)!==parseInt(f.year/20,10)?(angular.extend(f,{year:r.$date.getFullYear(),month:r.$date.getMonth(),date:r.$date.getDate()}),r.$build()):e.getFullYear()!==f.year&&(angular.extend(f,{year:r.$date.getFullYear(),month:r.$date.getMonth(),date:r.$date.getDate()}),r.$updateSelected())},build:function(){for(var t,a=f.year-f.year%(3*this.split),n=[],o=0;12>o;o++)t=new Date(a+o,0,1),n.push({date:t,label:i(t,this.format),selected:r.$isSelected(t),disabled:this.isDisabled(t)});d.title=n[0].label+"-"+n[n.length-1].label,d.showLabels=!1,d.rows=e(n,this.split),this.built=!0},isSelected:function(e){return r.$date&&e.getFullYear()===r.$date.getFullYear()},isDisabled:function(e){var t=+new Date(e.getFullYear()+1,0,0);return tl.maxDate},onKeyDown:function(e){if(r.$date){var t=r.$date.getFullYear(),a=new Date(r.$date);37===e.keyCode?a.setYear(t-1):38===e.keyCode?a.setYear(t-4):39===e.keyCode?a.setYear(t+1):40===e.keyCode&&a.setYear(t+4),this.isDisabled(a)||r.select(a,!0)}}}]);return{views:l.minView?Array.prototype.slice.call(h,l.minView):h,viewDate:f}}}]});
+"use strict";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",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,a,n,i,o,r,d,s){function l(t,a,n){function i(e){e.selected=l.$isSelected(e.date)}function o(){t[0].focus()}var l=d(t,angular.extend({},e,n)),g=n.scope,$=l.$options,m=l.$scope;$.startView&&($.startView-=$.minView);var f=r(l);l.$views=f.views;var h=f.viewDate;m.$mode=$.startView,m.$iconLeft=$.iconLeft,m.$iconRight=$.iconRight;var D=l.$views[m.$mode];m.$select=function(e){l.select(e)},m.$selectPane=function(e){l.$selectPane(e)},m.$toggleMode=function(){l.setMode((m.$mode+1)%l.$views.length)},l.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())&&(l.$date=e,D.update.call(D,e)),l.$build(!0)},l.updateDisabledDates=function(e){$.disabledDateRanges=e;for(var t=0,a=m.rows.length;a>t;t++)angular.forEach(m.rows[t],l.$setDisabledEl)},l.select=function(e,t){angular.isDate(a.$dateValue)||(a.$dateValue=new Date(e)),!m.$mode||t?(a.$setViewValue(angular.copy(e)),a.$render(),$.autoclose&&!t&&s(function(){l.hide(!0)})):(angular.extend(h,{year:e.getFullYear(),month:e.getMonth(),date:e.getDate()}),l.setMode(m.$mode-1),l.$build())},l.setMode=function(e){m.$mode=e,D=l.$views[m.$mode],l.$build()},l.$build=function(e){e===!0&&D.built||(e!==!1||D.built)&&D.build.call(D)},l.$updateSelected=function(){for(var e=0,t=m.rows.length;t>e;e++)angular.forEach(m.rows[e],i)},l.$isSelected=function(e){return D.isSelected(e)},l.$setDisabledEl=function(e){e.disabled=D.isDisabled(e.date)},l.$selectPane=function(e){var t=D.steps,a=new Date(Date.UTC(h.year+(t.year||0)*e,h.month+(t.month||0)*e,1));angular.extend(h,{year:a.getUTCFullYear(),month:a.getUTCMonth(),date:a.getUTCDate()}),l.$build()},l.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),c){var t=angular.element(e.target);"button"!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler("click")}},l.$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 m.$mode?m.$apply(function(){l.setMode(m.$mode-1)}):l.hide(!0);D.onKeyDown(e),g.$digest()}};var y=l.init;l.init=function(){return u&&$.useNative?(t.prop("type","date"),void t.css("-webkit-appearance","textfield")):(c&&(t.prop("type","text"),t.attr("readonly","true"),t.on("click",o)),void y())};var p=l.destroy;l.destroy=function(){u&&$.useNative&&t.off("click",o),p()};var w=l.show;l.show=function(){w(),s(function(){l.$element.on(c?"touchstart":"mousedown",l.$onMouseDown),$.keyboard&&t.on("keydown",l.$onKeyDown)},0,!1)};var b=l.hide;return l.hide=function(e){l.$isShown&&(l.$element.off(c?"touchstart":"mousedown",l.$onMouseDown),$.keyboard&&t.off("keydown",l.$onKeyDown),b(e))},l}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=o.getDefaultLocale()),l.defaults=e,l}]}).directive("bsDatepicker",["$window","$parse","$q","$dateFormatter","$dateParser","$datepicker",function(e,t,a,n,i,o){var r=(o.defaults,/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent));return{restrict:"EAC",require:"ngModel",link:function(e,t,a,d){function s(e){return e&&e.length?e:null}function l(e){if(angular.isDate(e)){var t=isNaN(g.$options.minDate)||e.getTime()>=g.$options.minDate,a=isNaN(g.$options.maxDate)||e.getTime()<=g.$options.maxDate,n=t&&a;d.$setValidity("date",n),d.$setValidity("min",t),d.$setValidity("max",a),n&&(d.$dateValue=e)}}function u(){return!d.$dateValue||isNaN(d.$dateValue.getTime())?"":m(d.$dateValue,c.dateFormat)}var c={scope:e,controller:d};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","autoclose","dateType","dateFormat","modelDateFormat","dayFormat","strictFormat","startWeek","startDate","useNative","lang","startView","minView","iconLeft","iconRight","daysOfWeekDisabled"],function(e){angular.isDefined(a[e])&&(c[e]=a[e])}),a.bsShow&&e.$watch(a.bsShow,function(e){g&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(datepicker),?/i)),e===!0?g.show():g.hide())});var g=o(t,d,c);c=g.$options,r&&c.useNative&&(c.dateFormat="yyyy-MM-dd");var $=c.lang,m=function(e,t){return n.formatDate(e,t,$)},f=i({format:c.dateFormat,lang:$,strict:c.strictFormat});angular.forEach(["minDate","maxDate"],function(e){angular.isDefined(a[e])&&a.$observe(e,function(t){g.$options[e]=f.getDateForAttribute(e,t),!isNaN(g.$options[e])&&g.$build(!1),l(d.$dateValue)})}),e.$watch(a.ngModel,function(){g.update(d.$dateValue)},!0),angular.isDefined(a.disabledDates)&&e.$watch(a.disabledDates,function(e,t){e=s(e),t=s(t),e&&g.updateDisabledDates(e)}),d.$parsers.unshift(function(e){if(!e)return d.$setValidity("date",!0),null;var t=f.parse(e,d.$dateValue);return!t||isNaN(t.getTime())?void d.$setValidity("date",!1):(l(t),"string"===c.dateType?m(t,c.modelDateFormat||c.dateFormat):"number"===c.dateType?d.$dateValue.getTime():"iso"===c.dateType?d.$dateValue.toISOString():new Date(d.$dateValue))}),d.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:"string"===c.dateType?f.parse(e,null,c.modelDateFormat):new Date(e),d.$dateValue=t,u()}),d.$render=function(){t.val(u())},e.$on("$destroy",function(){g&&g.destroy(),c=null,g=null})}}}]).provider("datepickerViews",function(){function e(e,t){for(var a=[];e.length>0;)a.push(e.splice(0,t));return a}function t(e,t){return(e%t+t)%t}this.defaults={dayFormat:"dd",daySplit:7};this.$get=["$dateFormatter","$dateParser","$sce",function(a,n,i){return function(o){var r=o.$scope,d=o.$options,s=d.lang,l=function(e,t){return a.formatDate(e,t,s)},u=n({format:d.dateFormat,lang:s,strict:d.strictFormat}),c=a.weekdaysShort(s),g=c.slice(d.startWeek).concat(c.slice(0,d.startWeek)),$=i.trustAsHtml(''+g.join(' ')+" "),m=o.$date||(d.startDate?u.getDateForAttribute("startDate",d.startDate):new Date),f={year:m.getFullYear(),month:m.getMonth(),date:m.getDate()},h=(6e4*m.getTimezoneOffset(),[{format:d.dayFormat,split:7,steps:{month:1},update:function(e,t){!this.built||t||e.getFullYear()!==f.year||e.getMonth()!==f.month?(angular.extend(f,{year:o.$date.getFullYear(),month:o.$date.getMonth(),date:o.$date.getDate()}),o.$build()):e.getDate()!==f.date&&(f.date=o.$date.getDate(),o.$updateSelected())},build:function(){var a=new Date(f.year,f.month,1),n=a.getTimezoneOffset(),i=new Date(+a-864e5*t(a.getDay()-d.startWeek,7)),s=i.getTimezoneOffset(),c=(new Date).toDateString();s!==n&&(i=new Date(+i+6e4*(s-n)));for(var g,m=[],h=0;42>h;h++)g=u.daylightSavingAdjust(new Date(i.getFullYear(),i.getMonth(),i.getDate()+h)),m.push({date:g,isToday:g.toDateString()===c,label:l(g,this.format),selected:o.$date&&this.isSelected(g),muted:g.getMonth()!==f.month,disabled:this.isDisabled(g)});r.title=l(a,d.monthTitleFormat),r.showLabels=!0,r.labels=$,r.rows=e(m,this.split),this.built=!0},isSelected:function(e){return o.$date&&e.getFullYear()===o.$date.getFullYear()&&e.getMonth()===o.$date.getMonth()&&e.getDate()===o.$date.getDate()},isDisabled:function(e){var t=e.getTime();if(td.maxDate)return!0;if(-1!==d.daysOfWeekDisabled.indexOf(e.getDay()))return!0;if(d.disabledDateRanges)for(var a=0;a=d.disabledDateRanges[a].start&&t<=d.disabledDateRanges[a].end)return!0;return!1},onKeyDown:function(e){if(o.$date){var t,a=o.$date.getTime();37===e.keyCode?t=new Date(a-864e5):38===e.keyCode?t=new Date(a-6048e5):39===e.keyCode?t=new Date(a+864e5):40===e.keyCode&&(t=new Date(a+6048e5)),this.isDisabled(t)||o.select(t,!0)}}},{name:"month",format:d.monthFormat,split:4,steps:{year:1},update:function(e){this.built&&e.getFullYear()===f.year?e.getMonth()!==f.month&&(angular.extend(f,{month:o.$date.getMonth(),date:o.$date.getDate()}),o.$updateSelected()):(angular.extend(f,{year:o.$date.getFullYear(),month:o.$date.getMonth(),date:o.$date.getDate()}),o.$build())},build:function(){for(var t,a=(new Date(f.year,0,1),[]),n=0;12>n;n++)t=new Date(f.year,n,1),a.push({date:t,label:l(t,this.format),selected:o.$isSelected(t),disabled:this.isDisabled(t)});r.title=l(t,d.yearTitleFormat),r.showLabels=!1,r.rows=e(a,this.split),this.built=!0},isSelected:function(e){return o.$date&&e.getFullYear()===o.$date.getFullYear()&&e.getMonth()===o.$date.getMonth()},isDisabled:function(e){var t=+new Date(e.getFullYear(),e.getMonth()+1,0);return td.maxDate},onKeyDown:function(e){if(o.$date){var t=o.$date.getMonth(),a=new Date(o.$date);37===e.keyCode?a.setMonth(t-1):38===e.keyCode?a.setMonth(t-4):39===e.keyCode?a.setMonth(t+1):40===e.keyCode&&a.setMonth(t+4),this.isDisabled(a)||o.select(a,!0)}}},{name:"year",format:d.yearFormat,split:4,steps:{year:12},update:function(e,t){!this.built||t||parseInt(e.getFullYear()/20,10)!==parseInt(f.year/20,10)?(angular.extend(f,{year:o.$date.getFullYear(),month:o.$date.getMonth(),date:o.$date.getDate()}),o.$build()):e.getFullYear()!==f.year&&(angular.extend(f,{year:o.$date.getFullYear(),month:o.$date.getMonth(),date:o.$date.getDate()}),o.$updateSelected())},build:function(){for(var t,a=f.year-f.year%(3*this.split),n=[],i=0;12>i;i++)t=new Date(a+i,0,1),n.push({date:t,label:l(t,this.format),selected:o.$isSelected(t),disabled:this.isDisabled(t)});r.title=n[0].label+"-"+n[n.length-1].label,r.showLabels=!1,r.rows=e(n,this.split),this.built=!0},isSelected:function(e){return o.$date&&e.getFullYear()===o.$date.getFullYear()},isDisabled:function(e){var t=+new Date(e.getFullYear()+1,0,0);return td.maxDate},onKeyDown:function(e){if(o.$date){var t=o.$date.getFullYear(),a=new Date(o.$date);37===e.keyCode?a.setYear(t-1):38===e.keyCode?a.setYear(t-4):39===e.keyCode?a.setYear(t+1):40===e.keyCode&&a.setYear(t+4),this.isDisabled(a)||o.select(a,!0)}}}]);return{views:d.minView?Array.prototype.slice.call(h,d.minView):h,viewDate:f}}}]});
//# sourceMappingURL=datepicker.min.js.map
\ No newline at end of file
diff --git a/dist/modules/datepicker.min.js.map b/dist/modules/datepicker.min.js.map
old mode 100755
new mode 100644
index f7718a299..79670472f
--- a/dist/modules/datepicker.min.js.map
+++ b/dist/modules/datepicker.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["datepicker/datepicker.js"],"names":[],"mappings":"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","file":"datepicker.min.js","sourcesContent":["'use strict';\n\nangular.module('mgcrea.ngStrap.datepicker', ['mgcrea.ngStrap.helpers.dateParser', 'mgcrea.ngStrap.tooltip'])\n\n .provider('$datepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\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 modelDateFormat: null,\n dayFormat: 'dd',\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, $locale, dateFilter, 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 = $locale.id;\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 var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), viewDate.date + ((steps.day || 0) * value)));\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 $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $datepicker.$onKeyDown);\n }\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, $locale, dateFilter, $datepicker, $dateParser) {\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', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 // Initialize parser\n var dateParser = $dateParser({format: options.dateFormat, lang: options.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 // Null values should correctly reset the model value & validity\n if(!viewValue) {\n controller.$setValidity('date', true);\n return;\n }\n var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedDate || isNaN(parsedDate.getTime())) {\n controller.$setValidity('date', false);\n return;\n } else {\n validateAgainstMinMaxDate(parsedDate);\n }\n if(options.dateType === 'string') {\n return dateFilter(parsedDate, options.modelDateFormat || options.dateFormat);\n } else if(options.dateType === 'number') {\n return controller.$dateValue.getTime();\n } else if(options.dateType === 'iso') {\n return controller.$dateValue.toISOString();\n } else {\n return new Date(controller.$dateValue);\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 {\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 = date;\n return controller.$dateValue;\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(!controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : dateFilter(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($locale, $sce, dateFilter, $dateParser) {\n\n return function(picker) {\n\n var scope = picker.$scope;\n var options = picker.$options;\n var dateParser = $dateParser();\n\n var weekDaysMin = $locale.DATETIME_FORMATS.SHORTDAY;\n var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n var weekDaysLabelsHtml = $sce.trustAsHtml('' + weekDaysLabels.join(' ') + ' ');\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 var timezoneOffset = startDate.getTimezoneOffset() * 6e4;\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) {\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 = new Date().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 = new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i);\n days.push({date: day, isToday: day.toDateString() === today, label: dateFilter(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n }\n scope.title = dateFilter(firstDayOfMonth, 'MMMM yyyy');\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: 'MMM',\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: dateFilter(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n }\n scope.title = dateFilter(month, 'yyyy');\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: 'yyyy',\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: dateFilter(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"],"sourceRoot":"/source/"}
\ No newline at end of file
+{"version":3,"sources":["datepicker/datepicker.js"],"names":[],"mappings":"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","file":"datepicker.min.js","sourcesContent":["'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 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 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 $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', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 // 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 if(options.dateType === 'string') {\n return formatDate(parsedDate, options.modelDateFormat || options.dateFormat);\n } else if(options.dateType === 'number') {\n return controller.$dateValue.getTime();\n } else if(options.dateType === 'iso') {\n return controller.$dateValue.toISOString();\n } else {\n return new Date(controller.$dateValue);\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 {\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 = date;\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('' + weekDaysLabels.join(' ') + ' ');\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 var timezoneOffset = startDate.getTimezoneOffset() * 6e4;\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) {\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 = new Date().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"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/dist/modules/datepicker.tpl.js b/dist/modules/datepicker.tpl.js
index 5e88cfd8a..94a985bc4 100644
--- a/dist/modules/datepicker.tpl.js
+++ b/dist/modules/datepicker.tpl.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/datepicker.tpl.min.js b/dist/modules/datepicker.tpl.min.js
index 39072abba..bcef5c36d 100644
--- a/dist/modules/datepicker.tpl.min.js
+++ b/dist/modules/datepicker.tpl.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/debounce.js b/dist/modules/debounce.js
index 9643e7fc6..e6d15191e 100644
--- a/dist/modules/debounce.js
+++ b/dist/modules/debounce.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/debounce.min.js b/dist/modules/debounce.min.js
index 2a4655352..747748e3d 100644
--- a/dist/modules/debounce.min.js
+++ b/dist/modules/debounce.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/debounce.min.js.map b/dist/modules/debounce.min.js.map
old mode 100755
new mode 100644
diff --git a/dist/modules/dimensions.js b/dist/modules/dimensions.js
index 0bf08147e..2c406f8a8 100644
--- a/dist/modules/dimensions.js
+++ b/dist/modules/dimensions.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/dimensions.min.js b/dist/modules/dimensions.min.js
index c7af761f0..632dbc08b 100644
--- a/dist/modules/dimensions.min.js
+++ b/dist/modules/dimensions.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/dimensions.min.js.map b/dist/modules/dimensions.min.js.map
old mode 100755
new mode 100644
diff --git a/dist/modules/dropdown.js b/dist/modules/dropdown.js
index 75217016a..1b1c3c73a 100644
--- a/dist/modules/dropdown.js
+++ b/dist/modules/dropdown.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -23,7 +23,7 @@ angular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])
delay: 0
};
- this.$get = ["$window", "$rootScope", "$tooltip", function($window, $rootScope, $tooltip) {
+ this.$get = ["$window", "$rootScope", "$tooltip", "$timeout", function($window, $rootScope, $tooltip, $timeout) {
var bodyEl = angular.element($window.document.body);
var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;
@@ -67,8 +67,12 @@ angular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])
var show = $dropdown.show;
$dropdown.show = function() {
show();
- options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);
- bodyEl.on('click', onBodyClick);
+ // use timeout to hookup the events to prevent
+ // event bubbling from being processed imediately.
+ $timeout(function() {
+ options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);
+ bodyEl.on('click', onBodyClick);
+ }, 0, false);
parentEl.hasClass('dropdown') && parentEl.addClass('open');
};
@@ -81,6 +85,12 @@ angular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])
hide();
};
+ var destroy = $dropdown.destroy;
+ $dropdown.destroy = function() {
+ bodyEl.off('click', onBodyClick);
+ destroy();
+ };
+
// Private functions
function onBodyClick(evt) {
diff --git a/dist/modules/dropdown.min.js b/dist/modules/dropdown.min.js
index ce3d518a5..1ac8fd471 100644
--- a/dist/modules/dropdown.min.js
+++ b/dist/modules/dropdown.min.js
@@ -1,9 +1,9 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";angular.module("mgcrea.ngStrap.dropdown",["mgcrea.ngStrap.tooltip"]).provider("$dropdown",function(){var e=this.defaults={animation:"am-fade",prefixClass:"dropdown",placement:"bottom-left",template:"dropdown/dropdown.tpl.html",trigger:"click",container:!1,keyboard:!0,html:!1,delay:0};this.$get=["$window","$rootScope","$tooltip",function(o,n,t){function r(o,r){function i(e){return e.target!==o[0]?e.target!==o[0]&&c.hide():void 0}{var c={},d=angular.extend({},e,r);c.$scope=d.scope&&d.scope.$new()||n.$new()}c=t(o,d);var s=o.parent();c.$onKeyDown=function(e){if(/(38|40)/.test(e.keyCode)){e.preventDefault(),e.stopPropagation();var o=angular.element(c.$element[0].querySelectorAll("li:not(.divider) a"));if(o.length){var n;angular.forEach(o,function(e,o){l&&l.call(e,":focus")&&(n=o)}),38===e.keyCode&&n>0?n--:40===e.keyCode&&n0?n--:40===e.keyCode&&n 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 options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n bodyEl.on('click', onBodyClick);\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 // 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'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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"],"sourceRoot":"/source/"}
\ No newline at end of file
+{"version":3,"sources":["dropdown/dropdown.js"],"names":[],"mappings":"qBASM,OAAA,2BAAA,oCAEA,YAAA,cAEA,GAAA,KAAA,UACA,UAAA,UACA,YAAA,WACF,UAAA,oDAEA,QAAA,qBAEE,UAAA,EACA,MAAA,gBAIE,MAAA,UAAA,aAAA,WAAA,WAAA,SAAA,EAAA,EAAA,EAAA,mBAsEF,QAAA,GAAA,0BAEA,EAAA,SAAA,EAAA,IAAA,EAAA,cAjEE,CAAA,GAAA,8BAIA,GAAA,OAAA,EAAA,OAAA,EAAA,MAAA,QAAA,EAAA,SAEE,EAAA,EAAA,MACA,GAAA,EAAA,WAIA,WAAA,SAAA,GACA,GAAA,UAAA,KAAA,EAAA,SAAA,CACA,EAAA,mBACE,iBAGF,IAAA,GAAA,QAAA,QAAA,EAAA,SAAA,GAAA,iBAAA,sBACA,IAAA,EAAA,OAAA,CACA,GAAA,EACA,SAAA,QAAA,EAAA,SAAA,EAAA,GACA,GAAA,EAAA,KAAA,EAAA,YAAA,EAAA,KAIF,KAAA,EAAA,SAAA,EAAA,EAAA,qCAEA,QAAA,YAAA,KAAA,EAAA,GACA,EAAA,GAAA,GAAA,GAAA,cAMI,GAAA,EAAA,OACF,KAAA,WACA,IAGF,EAAA,WACA,EAAA,UAAA,EAAA,SAAA,GAAA,UAAA,EAAA,YACE,EAAA,GAAA,QAAA,IACA,GAAA,GACA,EAAA,SAAA,aAAA,EAAA,SAAA,QAGF,IAAA,GAAA,EAAA,uBAEA,EAAA,WACA,EAAA,UAAA,EAAA,SAAA,IAAA,UAAA,EAAA,YACE,EAAA,IAAA,QAAA,GACA,EAAA,SAAA,aAAA,EAAA,YAAA,QACF,4BAIA,GAAA,QAAA,WACE,EAAA,IAAA,QAAA,GACA,UA/DF,GAAA,QAAA,QAAA,EAAA,SAAA,MACA,EAAA,QAAA,UAAA,iBAAA,QAAA,UAAA,uBAAA,QAAA,UAAA,oBAAA,QAAA,UAAA,mBAAA,QAAA,UAAA,wCAkFA,cAAA,UAAA,OAAA,YAAA,SAAA,EAAA,EAAA,mBAGE,aACF,0BAIE,IAAA,MAAA,EACF,SAAA,SAAA,YAAA,YAAA,QAAA,UAAA,WAAA,OAAA,YAAA,YAAA,SAAA,4CAKE,YAAA,EAAA,OAAA,EAAA,WAAA,SAAA,GACA,EAAA,QAAA,IACF,GAGA,EAAA,QAAA,EAAA,OAAA,EAAA,OAAA,SAAA,6BAEA,QAAA,SAAA,KAAA,IAAA,EAAA,MAAA,yBACA,KAAA,EAAA,EAAA,OAAA,EAAA,SAIA,IAAA,GAAA,EAAA,EAAA,EAGJ,GAAA,IAAA,WAAA,0BAED,EAAA","file":"dropdown.min.js","sourcesContent":["'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 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'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/dist/modules/dropdown.tpl.js b/dist/modules/dropdown.tpl.js
index fcd40d570..32d030ed0 100644
--- a/dist/modules/dropdown.tpl.js
+++ b/dist/modules/dropdown.tpl.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/dropdown.tpl.min.js b/dist/modules/dropdown.tpl.min.js
index b8fcdc2fb..1d897f9d5 100644
--- a/dist/modules/dropdown.tpl.min.js
+++ b/dist/modules/dropdown.tpl.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/modal.js b/dist/modules/modal.js
index d9efab720..fa872d417 100644
--- a/dist/modules/modal.js
+++ b/dist/modules/modal.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -128,13 +128,19 @@ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])
if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {
return;
}
- var parent;
+ var parent, after;
if(angular.isElement(options.container)) {
parent = options.container;
+ after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;
} else {
- parent = options.container ? findElement(options.container) : null;
+ if (options.container) {
+ parent = findElement(options.container);
+ after = parent[0].lastChild ? angular.element(parent[0].lastChild) : null;
+ } else {
+ parent = null;
+ after = options.element;
+ }
}
- var after = options.container ? null : options.element;
// Fetch a cloned element linked from template
modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});
@@ -158,8 +164,8 @@ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])
var promise = $animate.enter(modalElement, parent, after, enterAnimateCallback);
if(promise && promise.then) promise.then(enterAnimateCallback);
- scope.$isShown = true;
- scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
+ $modal.$isShown = scope.$isShown = true;
+ safeDigest(scope);
// Focus once the enter-animation has started
// Weird PhantomJS bug hack
var el = modalElement[0];
@@ -200,8 +206,8 @@ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])
if(options.backdrop) {
$animate.leave(backdropElement);
}
- scope.$isShown = false;
- scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
+ $modal.$isShown = scope.$isShown = false;
+ safeDigest(scope);
// Unbind events
if(options.backdrop) {
@@ -255,19 +261,25 @@ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])
// Helper functions
+ function safeDigest(scope) {
+ scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
+ }
+
function findElement(query, element) {
return angular.element((element || document).querySelectorAll(query));
}
+ var fetchPromises = {};
function fetchTemplate(template) {
- return $q.when($templateCache.get(template) || $http.get(template))
+ if(fetchPromises[template]) return fetchPromises[template];
+ return (fetchPromises[template] = $q.when($templateCache.get(template) || $http.get(template))
.then(function(res) {
if(angular.isObject(res)) {
$templateCache.put(template, res.data);
return res.data;
}
return res;
- });
+ }));
}
return ModalFactory;
diff --git a/dist/modules/modal.min.js b/dist/modules/modal.min.js
index 2f0d02293..a6edd6225 100644
--- a/dist/modules/modal.min.js
+++ b/dist/modules/modal.min.js
@@ -1,9 +1,9 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";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,t,o,a,i,r,c,l,s){function u(n){function a(){v.$emit(u.prefixEvent+".show",l)}function i(){v.$emit(u.prefixEvent+".hide",l),h.removeClass(u.prefixClass+"-open"),u.animation&&h.removeClass(u.prefixClass+"-with-"+u.animation)}function r(e){e.target===e.currentTarget&&("static"===u.backdrop?l.focus():l.hide())}var l={},u=l.$options=angular.extend({},e,n);l.$promise=m(u.template);var v=l.$scope=u.scope&&u.scope.$new()||t.$new();u.element||u.container||(u.container="body"),p(["title","content"],function(e){u[e]&&(v[e]=s.trustAsHtml(u[e]))}),v.$hide=function(){v.$$postDigest(function(){l.hide()})},v.$show=function(){v.$$postDigest(function(){l.show()})},v.$toggle=function(){v.$$postDigest(function(){l.toggle()})},u.contentTemplate&&(l.$promise=l.$promise.then(function(e){var t=angular.element(e);return m(u.contentTemplate).then(function(e){var o=d('[ng-bind="content"]',t[0]).removeAttr("ng-bind").html(e);return n.template||o.next().remove(),t[0].outerHTML})}));var b,w,k=angular.element('
');return l.$promise.then(function(e){angular.isObject(e)&&(e=e.data),u.html&&(e=e.replace(g,'ng-bind-html="')),e=f.apply(e),b=o(e),l.init()}),l.init=function(){u.show&&v.$$postDigest(function(){l.show()})},l.destroy=function(){w&&(w.remove(),w=null),k&&(k.remove(),k=null),v.$destroy()},l.show=function(){if(!v.$isShown&&!v.$emit(u.prefixEvent+".show.before",l).defaultPrevented){var e;e=angular.isElement(u.container)?u.container:u.container?d(u.container):null;var n=u.container?null:u.element;w=l.$element=b(v,function(){}),w.css({display:"block"}).addClass(u.placement),u.animation&&(u.backdrop&&k.addClass(u.backdropAnimation),w.addClass(u.animation)),u.backdrop&&c.enter(k,h,null);var t=c.enter(w,e,n,a);t&&t.then&&t.then(a),v.$isShown=!0,v.$$phase||v.$root&&v.$root.$$phase||v.$digest();var o=w[0];$(function(){o.focus()}),h.addClass(u.prefixClass+"-open"),u.animation&&h.addClass(u.prefixClass+"-with-"+u.animation),u.backdrop&&(w.on("click",r),k.on("click",r)),u.keyboard&&w.on("keyup",l.$onKeyUp)}},l.hide=function(){if(v.$isShown&&!v.$emit(u.prefixEvent+".hide.before",l).defaultPrevented){var e=c.leave(w,i);e&&e.then&&e.then(i),u.backdrop&&c.leave(k),v.$isShown=!1,v.$$phase||v.$root&&v.$root.$$phase||v.$digest(),u.backdrop&&(w.off("click",r),k.off("click",r)),u.keyboard&&w.off("keyup",l.$onKeyUp)}},l.toggle=function(){v.$isShown?l.hide():l.show()},l.focus=function(){w[0].focus()},l.$onKeyUp=function(e){27===e.which&&v.$isShown&&(l.hide(),e.stopPropagation())},l}function d(e,n){return angular.element((n||document).querySelectorAll(e))}function m(e){return a.when(i.get(e)||r.get(e)).then(function(n){return angular.isObject(n)?(i.put(e,n.data),n.data):n})}var p=angular.forEach,f=String.prototype.trim,$=n.requestAnimationFrame||n.setTimeout,h=angular.element(n.document.body),g=/ng-bind="/gi;return u}]}).directive("bsModal",["$window","$sce","$modal",function(e,n,t){return{restrict:"EAC",scope:!0,link:function(e,o,a){var i={scope:e,element:o,show:!1};angular.forEach(["template","contentTemplate","placement","backdrop","keyboard","html","container","animation"],function(e){angular.isDefined(a[e])&&(i[e]=a[e])}),angular.forEach(["title","content"],function(t){a[t]&&a.$observe(t,function(o){e[t]=n.trustAsHtml(o)})}),a.bsModal&&e.$watch(a.bsModal,function(n){angular.isObject(n)?angular.extend(e,n):e.content=n},!0);var r=t(i);o.on(a.trigger||"click",r.toggle),e.$on("$destroy",function(){r&&r.destroy(),i=null,r=null})}}}]);
+"use strict";angular.module("mgcrea.ngStrap.modal",["mgcrea.ngStrap.helpers.dimensions"]).provider("$modal",function(){var n=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(e,t,o,a,i,r,l,c,s){function u(e){function a(){b.$emit(u.prefixEvent+".show",c)}function i(){b.$emit(u.prefixEvent+".hide",c),g.removeClass(u.prefixClass+"-open"),u.animation&&g.removeClass(u.prefixClass+"-with-"+u.animation)}function r(n){n.target===n.currentTarget&&("static"===u.backdrop?c.focus():c.hide())}var c={},u=c.$options=angular.extend({},n,e);c.$promise=p(u.template);var b=c.$scope=u.scope&&u.scope.$new()||t.$new();u.element||u.container||(u.container="body"),f(["title","content"],function(n){u[n]&&(b[n]=s.trustAsHtml(u[n]))}),b.$hide=function(){b.$$postDigest(function(){c.hide()})},b.$show=function(){b.$$postDigest(function(){c.show()})},b.$toggle=function(){b.$$postDigest(function(){c.toggle()})},u.contentTemplate&&(c.$promise=c.$promise.then(function(n){var t=angular.element(n);return p(u.contentTemplate).then(function(n){var o=m('[ng-bind="content"]',t[0]).removeAttr("ng-bind").html(n);return e.template||o.next().remove(),t[0].outerHTML})}));var w,k,y=angular.element('
');return c.$promise.then(function(n){angular.isObject(n)&&(n=n.data),u.html&&(n=n.replace(v,'ng-bind-html="')),n=$.apply(n),w=o(n),c.init()}),c.init=function(){u.show&&b.$$postDigest(function(){c.show()})},c.destroy=function(){k&&(k.remove(),k=null),y&&(y.remove(),y=null),b.$destroy()},c.show=function(){if(!b.$isShown&&!b.$emit(u.prefixEvent+".show.before",c).defaultPrevented){var n,e;angular.isElement(u.container)?(n=u.container,e=u.container[0].lastChild?angular.element(u.container[0].lastChild):null):u.container?(n=m(u.container),e=n[0].lastChild?angular.element(n[0].lastChild):null):(n=null,e=u.element),k=c.$element=w(b,function(){}),k.css({display:"block"}).addClass(u.placement),u.animation&&(u.backdrop&&y.addClass(u.backdropAnimation),k.addClass(u.animation)),u.backdrop&&l.enter(y,g,null);var t=l.enter(k,n,e,a);t&&t.then&&t.then(a),c.$isShown=b.$isShown=!0,d(b);var o=k[0];h(function(){o.focus()}),g.addClass(u.prefixClass+"-open"),u.animation&&g.addClass(u.prefixClass+"-with-"+u.animation),u.backdrop&&(k.on("click",r),y.on("click",r)),u.keyboard&&k.on("keyup",c.$onKeyUp)}},c.hide=function(){if(b.$isShown&&!b.$emit(u.prefixEvent+".hide.before",c).defaultPrevented){var n=l.leave(k,i);n&&n.then&&n.then(i),u.backdrop&&l.leave(y),c.$isShown=b.$isShown=!1,d(b),u.backdrop&&(k.off("click",r),y.off("click",r)),u.keyboard&&k.off("keyup",c.$onKeyUp)}},c.toggle=function(){b.$isShown?c.hide():c.show()},c.focus=function(){k[0].focus()},c.$onKeyUp=function(n){27===n.which&&b.$isShown&&(c.hide(),n.stopPropagation())},c}function d(n){n.$$phase||n.$root&&n.$root.$$phase||n.$digest()}function m(n,e){return angular.element((e||document).querySelectorAll(n))}function p(n){return b[n]?b[n]:b[n]=a.when(i.get(n)||r.get(n)).then(function(e){return angular.isObject(e)?(i.put(n,e.data),e.data):e})}var f=angular.forEach,$=String.prototype.trim,h=e.requestAnimationFrame||e.setTimeout,g=angular.element(e.document.body),v=/ng-bind="/gi,b={};return u}]}).directive("bsModal",["$window","$sce","$modal",function(n,e,t){return{restrict:"EAC",scope:!0,link:function(n,o,a){var i={scope:n,element:o,show:!1};angular.forEach(["template","contentTemplate","placement","backdrop","keyboard","html","container","animation"],function(n){angular.isDefined(a[n])&&(i[n]=a[n])}),angular.forEach(["title","content"],function(t){a[t]&&a.$observe(t,function(o){n[t]=e.trustAsHtml(o)})}),a.bsModal&&n.$watch(a.bsModal,function(e){angular.isObject(e)?angular.extend(n,e):n.content=e},!0);var r=t(i);o.on(a.trigger||"click",r.toggle),n.$on("$destroy",function(){r&&r.destroy(),i=null,r=null})}}}]);
//# sourceMappingURL=modal.min.js.map
\ No newline at end of file
diff --git a/dist/modules/modal.min.js.map b/dist/modules/modal.min.js.map
old mode 100755
new mode 100644
index 4499b8479..ddb3f9b5f
--- a/dist/modules/modal.min.js.map
+++ b/dist/modules/modal.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["modal/modal.js"],"names":[],"mappings":"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","file":"modal.min.js","sourcesContent":["'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 // 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\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('
');\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(scope.$isShown) return;\n\n if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n return;\n }\n var parent;\n if(angular.isElement(options.container)) {\n parent = options.container;\n } else {\n parent = options.container ? findElement(options.container) : null;\n }\n var after = options.container ? null : options.element;\n\n // Fetch a cloned element linked from template\n modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\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 scope.$isShown = true;\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\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 }\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(!scope.$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 scope.$isShown = false;\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n\n // Unbind events\n if(options.backdrop) {\n modalElement.off('click', hideOnBackdropClick);\n backdropElement.off('click', hideOnBackdropClick);\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 scope.$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 && scope.$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 return $modal;\n\n }\n\n // Helper functions\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n function fetchTemplate(template) {\n return $q.when($templateCache.get(template) || $http.get(template))\n .then(function(res) {\n if(angular.isObject(res)) {\n $templateCache.put(template, res.data);\n return res.data;\n }\n return res;\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'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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"],"sourceRoot":"/source/"}
\ No newline at end of file
+{"version":3,"sources":["modal/modal.js"],"names":[],"mappings":"qBASM,OAAA,wBAAA,+CAEA,SAAA,cAEA,GAAA,KAAA,UACA,UAAA,UACA,kBAAA,UACA,YAAA,QACA,YAAA,QACA,UAAA,MACA,SAAA,uBACF,iBAAA,eAEA,QAAA,iBAEE,UAAA,EACA,MAAA,EACA,MAAA,4JAWE,GAAA,WAyJE,OACE,MAAA,EAAA,YAAA,QAAA,gBA+BJ,EAAA,MAAA,EAAA,YAAA,QAAA,wCAEE,EAAA,6DA4BJ,QAAA,GAAA,gCAEA,WAAA,EAAA,SAAA,EAAA,QAAA,EAAA,WAvNI,MAGF,EAAA,EAAA,SAAA,QAAA,UAAA,EAAA,EACA,GAAA,SAAA,EAAA,EAAA,aACE,GAAA,EAAA,OAAA,EAAA,OAAA,EAAA,MAAA,QAAA,EAAA,MACF,GAAA,SAAA,EAAA,mCAKI,QAAA,WAAA,SAAA,GACF,EAAA,KAAA,EAAA,GAAA,EAAA,YAAA,EAAA,SAIE,MAAA,WACF,EAAA,aAAA,WACF,EAAA,YAGI,MAAA,WACF,EAAA,aAAA,WACF,EAAA,UAGA,EAAA,QAAA,WACE,EAAA,aAAA,WACE,EAAA,cAKE,oBACA,SAAA,EAAA,SAAA,KAAA,SAAA,GACF,GAAA,GAAA,QAAA,QAAA,EACF,OAAA,GAAA,EAAA,iBACF,KAAA,SAAA,oEAIA,OADA,GAAA,UAAA,EAAA,OAAA,SACA,EAAA,GAAA,kBAME,GAAA,EACF,EAAA,QAAA,QAAA,eAAA,EAAA,YAAA,eA0KA,oCAxKA,QAAA,SAAA,KAAA,EAAA,EAAA,gDAEE,EAAA,EAAA,MAAA,GACA,EAAA,EAAA,KACE,WAGF,KAAA,mBAIF,EAAA,aAAA,yBAOE,QAAA,WAGA,eAEA,EAAA,UAGF,EAAA,iBAKE,EAAA,cAIA,KAAA,eACE,EAAA,WAEF,EAAA,MAAA,EAAA,YAAA,eAAA,GAAA,iBAAA,IAGI,GAAA,CACF,SAAA,UAAA,EAAA,cACE,EAAA,YACA,EAAA,UAAA,GAAA,UAAA,QAAA,QAAA,EAAA,UAAA,GAAA,WAAA,MAEJ,EAAA,4BAEA,EAAA,EAAA,GAAA,UAAA,QAAA,QAAA,EAAA,GAAA,WAAA,cAGA,EAAA,EAAA,WAKE,EAAA,SAAA,EAAA,EAAA,gBAGA,KAAA,QAAA,UAAA,SAAA,EAAA,WAGF,EAAA,YACE,EAAA,UACF,EAAA,SAAA,EAAA,mBAEA,EAAA,SAAA,EAAA,wBAIA,EAAA,MAAA,EAAA,EAAA,KAIA,IAAA,GAAA,EAAA,MAAA,EAAA,EAAA,EAAA,EACA,IAAA,EAAA,MAAA,EAAA,KAAA,GAEA,EAAA,SAAA,EAAA,UAAA,UAIE,GAAA,EAAA,EACF,GAAA,yBAIE,SAAA,EAAA,YAAA,SACA,EAAA,WACF,EAAA,SAAA,EAAA,YAAA,SAAA,EAAA,WAIF,EAAA,2BAEA,EAAA,GAAA,QAAA,IAEA,EAAA,uCASE,KAAA,WACA,GAAA,EAAA,qEAKA,GAAA,GAAA,EAAA,MAAA,EAAA,wBAKA,EAAA,UACE,EAAA,MAAA,GAEF,EAAA,SAAA,EAAA,UAAA,EACA,EAAA,GAGF,EAAA,4BAEA,EAAA,IAAA,QAAA,IAEE,EAAA,UACA,EAAA,IAAA,QAAA,EAAA,cAYA,OAAA,4DAOA,EAAA,GAAA,SAKF,EAAA,SAAA,SAAA,GAEA,KAAA,EAAA,OAAA,EAAA,oBAEA,EAAA,oBAYA,gBAOF,EAAA,SAAA,EAAA,OAAA,EAAA,MAAA,SAAA,EAAA,kBAGE,GAAA,EAAA,GACA,MAAA,SAAA,SAAA,GAAA,UAAA,iBAAA,YAIE,GAAA,SACA,GAAA,GAAA,EAAA,GACF,EAAA,GAAA,EAAA,KAAA,EAAA,IAAA,IAAA,EAAA,IAAA,IACF,KAAA,SAAA,+BAEA,EAAA,IAAA,EAAA,EAAA,wCArPE,EAAA,OAAA,UAAA,6CAEA,EAAA,QAAA,QAAA,EAAA,SAAA,MACA,EAAA,0CA+PA,WAAA,UAAA,OAAA,SAAA,SAAA,EAAA,EAAA,mBAGE,aACF,0BAIE,IAAA,MAAA,EAAA,QAAA,EAAA,MAAA,WACE,SAAA,WAAA,kBAAA,YAAA,WAAA,WAAA,OAAA,YAAA,aAAA,SAAA,GACF,QAAA,UAAA,EAAA,MAAA,EAAA,GAAA,EAAA,MAIF,QAAA,SAAA,QAAA,WAAA,SAAA,GACE,EAAA,IAAA,EAAA,SAAA,EAAA,SAAA,GACE,EAAA,GAAA,EAAA,YAAA,iDAMJ,QAAA,SAAA,GACA,QAAA,OAAA,EAAA,GAEA,EAAA,QAAA,UAKE,GAAA,EAAA,EAGF,GAAA,GAAA,EAAA,SAAA,QAAA,EAAA,QAGJ,EAAA,IAAA,WAAA,0BAED,EAAA","file":"modal.min.js","sourcesContent":["'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 // 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\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('
');\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(scope.$isShown) return;\n\n if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n 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].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 // 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 }\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(!scope.$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 }\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 scope.$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 && scope.$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 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] = $q.when($templateCache.get(template) || $http.get(template))\n .then(function(res) {\n if(angular.isObject(res)) {\n $templateCache.put(template, res.data);\n return res.data;\n }\n return res;\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'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/dist/modules/modal.tpl.js b/dist/modules/modal.tpl.js
index 3171bc8fd..0e4406811 100644
--- a/dist/modules/modal.tpl.js
+++ b/dist/modules/modal.tpl.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/modal.tpl.min.js b/dist/modules/modal.tpl.min.js
index 53f951f36..662aa6a03 100644
--- a/dist/modules/modal.tpl.min.js
+++ b/dist/modules/modal.tpl.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/navbar.js b/dist/modules/navbar.js
index b06cc8a25..448001e32 100644
--- a/dist/modules/navbar.js
+++ b/dist/modules/navbar.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/navbar.min.js b/dist/modules/navbar.min.js
index 06d532122..5188f28d7 100644
--- a/dist/modules/navbar.min.js
+++ b/dist/modules/navbar.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/navbar.min.js.map b/dist/modules/navbar.min.js.map
old mode 100755
new mode 100644
diff --git a/dist/modules/parse-options.js b/dist/modules/parse-options.js
index 85b68b4be..f87353ef1 100644
--- a/dist/modules/parse-options.js
+++ b/dist/modules/parse-options.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/parse-options.min.js b/dist/modules/parse-options.min.js
index 05d18150b..65465119e 100644
--- a/dist/modules/parse-options.min.js
+++ b/dist/modules/parse-options.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/parse-options.min.js.map b/dist/modules/parse-options.min.js.map
old mode 100755
new mode 100644
diff --git a/dist/modules/popover.js b/dist/modules/popover.js
index 473f53c06..ad4e4c6cc 100644
--- a/dist/modules/popover.js
+++ b/dist/modules/popover.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/popover.min.js b/dist/modules/popover.min.js
index f36281469..ce657be7f 100644
--- a/dist/modules/popover.min.js
+++ b/dist/modules/popover.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/popover.min.js.map b/dist/modules/popover.min.js.map
old mode 100755
new mode 100644
diff --git a/dist/modules/popover.tpl.js b/dist/modules/popover.tpl.js
index 472ac8075..b428b47c1 100644
--- a/dist/modules/popover.tpl.js
+++ b/dist/modules/popover.tpl.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/popover.tpl.min.js b/dist/modules/popover.tpl.min.js
index 98877c925..320a44c31 100644
--- a/dist/modules/popover.tpl.min.js
+++ b/dist/modules/popover.tpl.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/raf.js b/dist/modules/raf.js
index 8c733f3e4..ad2f4b313 100644
--- a/dist/modules/raf.js
+++ b/dist/modules/raf.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/raf.min.js b/dist/modules/raf.min.js
index 0df17f69c..524e79b0f 100644
--- a/dist/modules/raf.min.js
+++ b/dist/modules/raf.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/raf.min.js.map b/dist/modules/raf.min.js.map
old mode 100755
new mode 100644
diff --git a/dist/modules/scrollspy.js b/dist/modules/scrollspy.js
index 77365a399..759ee1995 100644
--- a/dist/modules/scrollspy.js
+++ b/dist/modules/scrollspy.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -131,7 +131,9 @@ angular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', '
};
$scrollspy.checkPositionWithEventLoop = function() {
- setTimeout(this.checkPosition, 1);
+ // IE 9 throws an error if we use 'this' instead of '$scrollspy'
+ // in this setTimeout call
+ setTimeout($scrollspy.checkPosition, 1);
};
// Protected methods
diff --git a/dist/modules/scrollspy.min.js b/dist/modules/scrollspy.min.js
index 160d7403b..42a543b80 100644
--- a/dist/modules/scrollspy.min.js
+++ b/dist/modules/scrollspy.min.js
@@ -1,9 +1,9 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";angular.module("mgcrea.ngStrap.scrollspy",["mgcrea.ngStrap.helpers.debounce","mgcrea.ngStrap.helpers.dimensions"]).provider("$scrollspy",function(){var e=this.$$spies={},t=this.defaults={debounce:150,throttle:100,offset:100};this.$get=["$window","$document","$rootScope","dimensions","debounce","throttle",function(n,o,r,c,i,s){function a(e,t){return e[0].nodeName&&e[0].nodeName.toLowerCase()===t.toLowerCase()}function l(o){var l=angular.extend({},t,o);l.element||(l.element=p);var d=a(l.element,"body"),h=d?u:l.element,m=d?"window":l.id;if(e[m])return e[m].$$count++,e[m];var g,v,$,k,E,T,y,b,C={},S=C.$trackedElements=[],L=[];return C.init=function(){this.$$count=1,k=i(this.checkPosition,l.debounce),E=s(this.checkPosition,l.throttle),h.on("click",this.checkPositionWithEventLoop),u.on("resize",k),h.on("scroll",E),T=i(this.checkOffsets,l.debounce),g=r.$on("$viewContentLoaded",T),v=r.$on("$includeContentLoaded",T),T(),m&&(e[m]=C)},C.destroy=function(){this.$$count--,this.$$count>0||(h.off("click",this.checkPositionWithEventLoop),u.off("resize",k),h.off("scroll",k),g(),v(),m&&delete e[m])},C.checkPosition=function(){if(L.length){if(b=(d?n.pageYOffset:h.prop("scrollTop"))||0,y=Math.max(n.innerHeight,f.prop("clientHeight")),bL[e+1].offsetTop))return C.$activateElement(L[e])}},C.checkPositionWithEventLoop=function(){setTimeout(this.checkPosition,1)},C.$activateElement=function(e){if($){var t=C.$getTrackedElement($);t&&(t.source.removeClass("active"),a(t.source,"li")&&a(t.source.parent().parent(),"li")&&t.source.parent().parent().removeClass("active"))}$=e.target,e.source.addClass("active"),a(e.source,"li")&&a(e.source.parent().parent(),"li")&&e.source.parent().parent().addClass("active")},C.$getTrackedElement=function(e){return S.filter(function(t){return t.target===e})[0]},C.checkOffsets=function(){angular.forEach(S,function(e){var t=document.querySelector(e.target);e.offsetTop=t?c.offset(t).top:null,l.offset&&null!==e.offsetTop&&(e.offsetTop-=1*l.offset)}),L=S.filter(function(e){return null!==e.offsetTop}).sort(function(e,t){return e.offsetTop-t.offsetTop}),k()},C.trackElement=function(e,t){S.push({target:e,source:t})},C.untrackElement=function(e,t){for(var n,o=S.length;o--;)if(S[o].target===e&&S[o].source===t){n=o;break}S=S.splice(n,1)},C.activate=function(e){S[e].addClass("active")},C.init(),C}var u=angular.element(n),f=angular.element(o.prop("documentElement")),p=angular.element(n.document.body);return l}]}).directive("bsScrollspy",["$rootScope","debounce","dimensions","$scrollspy",function(e,t,n,o){return{restrict:"EAC",link:function(e,t,n){var r={scope:e};angular.forEach(["offset","target"],function(e){angular.isDefined(n[e])&&(r[e]=n[e])});var c=o(r);c.trackElement(r.target,t),e.$on("$destroy",function(){c&&(c.untrackElement(r.target,t),c.destroy()),r=null,c=null})}}}]).directive("bsScrollspyList",["$rootScope","debounce","dimensions","$scrollspy",function(){return{restrict:"A",compile:function(e){var t=e[0].querySelectorAll("li > a[href]");angular.forEach(t,function(e){var t=angular.element(e);t.parent().attr("bs-scrollspy","").attr("data-target",t.attr("href"))})}}}]);
+"use strict";angular.module("mgcrea.ngStrap.scrollspy",["mgcrea.ngStrap.helpers.debounce","mgcrea.ngStrap.helpers.dimensions"]).provider("$scrollspy",function(){var e=this.$$spies={},t=this.defaults={debounce:150,throttle:100,offset:100};this.$get=["$window","$document","$rootScope","dimensions","debounce","throttle",function(n,o,r,c,i,s){function a(e,t){return e[0].nodeName&&e[0].nodeName.toLowerCase()===t.toLowerCase()}function l(o){var l=angular.extend({},t,o);l.element||(l.element=p);var d=a(l.element,"body"),h=d?u:l.element,m=d?"window":l.id;if(e[m])return e[m].$$count++,e[m];var g,v,$,k,E,T,y,b,C={},S=C.$trackedElements=[],L=[];return C.init=function(){this.$$count=1,k=i(this.checkPosition,l.debounce),E=s(this.checkPosition,l.throttle),h.on("click",this.checkPositionWithEventLoop),u.on("resize",k),h.on("scroll",E),T=i(this.checkOffsets,l.debounce),g=r.$on("$viewContentLoaded",T),v=r.$on("$includeContentLoaded",T),T(),m&&(e[m]=C)},C.destroy=function(){this.$$count--,this.$$count>0||(h.off("click",this.checkPositionWithEventLoop),u.off("resize",k),h.off("scroll",k),g(),v(),m&&delete e[m])},C.checkPosition=function(){if(L.length){if(b=(d?n.pageYOffset:h.prop("scrollTop"))||0,y=Math.max(n.innerHeight,f.prop("clientHeight")),bL[e+1].offsetTop))return C.$activateElement(L[e])}},C.checkPositionWithEventLoop=function(){setTimeout(C.checkPosition,1)},C.$activateElement=function(e){if($){var t=C.$getTrackedElement($);t&&(t.source.removeClass("active"),a(t.source,"li")&&a(t.source.parent().parent(),"li")&&t.source.parent().parent().removeClass("active"))}$=e.target,e.source.addClass("active"),a(e.source,"li")&&a(e.source.parent().parent(),"li")&&e.source.parent().parent().addClass("active")},C.$getTrackedElement=function(e){return S.filter(function(t){return t.target===e})[0]},C.checkOffsets=function(){angular.forEach(S,function(e){var t=document.querySelector(e.target);e.offsetTop=t?c.offset(t).top:null,l.offset&&null!==e.offsetTop&&(e.offsetTop-=1*l.offset)}),L=S.filter(function(e){return null!==e.offsetTop}).sort(function(e,t){return e.offsetTop-t.offsetTop}),k()},C.trackElement=function(e,t){S.push({target:e,source:t})},C.untrackElement=function(e,t){for(var n,o=S.length;o--;)if(S[o].target===e&&S[o].source===t){n=o;break}S=S.splice(n,1)},C.activate=function(e){S[e].addClass("active")},C.init(),C}var u=angular.element(n),f=angular.element(o.prop("documentElement")),p=angular.element(n.document.body);return l}]}).directive("bsScrollspy",["$rootScope","debounce","dimensions","$scrollspy",function(e,t,n,o){return{restrict:"EAC",link:function(e,t,n){var r={scope:e};angular.forEach(["offset","target"],function(e){angular.isDefined(n[e])&&(r[e]=n[e])});var c=o(r);c.trackElement(r.target,t),e.$on("$destroy",function(){c&&(c.untrackElement(r.target,t),c.destroy()),r=null,c=null})}}}]).directive("bsScrollspyList",["$rootScope","debounce","dimensions","$scrollspy",function(){return{restrict:"A",compile:function(e){var t=e[0].querySelectorAll("li > a[href]");angular.forEach(t,function(e){var t=angular.element(e);t.parent().attr("bs-scrollspy","").attr("data-target",t.attr("href"))})}}}]);
//# sourceMappingURL=scrollspy.min.js.map
\ No newline at end of file
diff --git a/dist/modules/scrollspy.min.js.map b/dist/modules/scrollspy.min.js.map
old mode 100755
new mode 100644
index 37927e70a..34c0857b7
--- a/dist/modules/scrollspy.min.js.map
+++ b/dist/modules/scrollspy.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["scrollspy/scrollspy.js"],"names":[],"mappings":"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","file":"scrollspy.min.js","sourcesContent":["'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', debouncedCheckPosition);\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 setTimeout(this.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"],"sourceRoot":"/source/"}
\ No newline at end of file
+{"version":3,"sources":["scrollspy/scrollspy.js"],"names":[],"mappings":"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","file":"scrollspy.min.js","sourcesContent":["'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', debouncedCheckPosition);\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"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/dist/modules/select.js b/dist/modules/select.js
index 1ac41cf8f..ba89c6354 100644
--- a/dist/modules/select.js
+++ b/dist/modules/select.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -32,7 +32,7 @@ angular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStr
iconCheckmark: 'glyphicon glyphicon-ok'
};
- this.$get = ["$window", "$document", "$rootScope", "$tooltip", function($window, $document, $rootScope, $tooltip) {
+ this.$get = ["$window", "$document", "$rootScope", "$tooltip", "$timeout", function($window, $document, $rootScope, $tooltip, $timeout) {
var bodyEl = angular.element($window.document.body);
var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
@@ -204,10 +204,14 @@ angular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStr
if(options.multiple) {
$select.$element.addClass('select-multiple');
}
- $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);
- if(options.keyboard) {
- element.on('keydown', $select.$onKeyDown);
- }
+ // use timeout to hookup the events to prevent
+ // event bubbling from being processed imediately.
+ $timeout(function() {
+ $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);
+ if(options.keyboard) {
+ element.on('keydown', $select.$onKeyDown);
+ }
+ }, 0, false);
};
var _hide = $select.hide;
@@ -298,6 +302,12 @@ angular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStr
element.html((selected ? selected : options.placeholder) + defaults.caretHtml);
};
+ if(options.multiple){
+ controller.$isEmpty = function(value){
+ return !value || value.length === 0;
+ };
+ }
+
// Garbage collection
scope.$on('$destroy', function() {
if (select) select.destroy();
diff --git a/dist/modules/select.min.js b/dist/modules/select.min.js
index 3b421a349..baff3da71 100644
--- a/dist/modules/select.min.js
+++ b/dist/modules/select.min.js
@@ -1,9 +1,9 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";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:' ',placeholder:"Choose among the following...",maxLength:3,maxLengthHtml:"selected",iconCheckmark:"glyphicon glyphicon-ok"};this.$get=["$window","$document","$rootScope","$tooltip",function(t,n,a,i){function l(t,n,a){var l={},o=angular.extend({},e,a);l=i(t,o);var r=l.$scope;r.$matches=[],r.$activeIndex=0,r.$isMultiple=o.multiple,r.$showAllNoneButtons=o.allNoneButtons&&o.multiple,r.$iconCheckmark=o.iconCheckmark,r.$activate=function(e){r.$$postDigest(function(){l.activate(e)})},r.$select=function(e){r.$$postDigest(function(){l.select(e)})},r.$isVisible=function(){return l.$isVisible()},r.$isActive=function(e){return l.$isActive(e)},r.$selectAll=function(){for(var e=0;e=r.$matches.length&&(r.$activeIndex=o.multiple?[]:0)},l.$isVisible=function(){return o.minLength&&n?r.$matches.length&&n.$viewValue.length>=o.minLength:r.$matches.length},l.$isActive=function(e){return o.multiple?-1!==r.$activeIndex.indexOf(e):r.$activeIndex===e},l.$getIndex=function(e){var t=r.$matches.length,n=t;if(t){for(n=t;n--&&r.$matches[n].value!==e;);if(!(0>n))return n}},l.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),c){var t=angular.element(e.target);t.triggerHandler("click")}},l.$onKeyDown=function(e){if(/(9|13|38|40)/.test(e.keyCode)){if(e.preventDefault(),e.stopPropagation(),!o.multiple&&(13===e.keyCode||9===e.keyCode))return l.select(r.$activeIndex);38===e.keyCode&&r.$activeIndex>0?r.$activeIndex--:40===e.keyCode&&r.$activeIndex'),r.after(t)}var s=i(n.ngOptions),u=a(t,o,c),$=s.$match[7].replace(/\|.+/,"").trim();e.$watch($,function(){s.valuesFn(e,o).then(function(e){u.update(e),o.$render()})},!0),e.$watch(n.ngModel,function(){u.$updateActiveIndex(),o.$render()},!0),o.$render=function(){var e,n;c.multiple&&angular.isArray(o.$modelValue)?(e=o.$modelValue.map(function(e){return n=u.$getIndex(e),angular.isDefined(n)?u.$scope.$matches[n].label:!1}).filter(angular.isDefined),e=e.length>(c.maxLength||l.maxLength)?e.length+" "+(c.maxLengthHtml||l.maxLengthHtml):e.join(", ")):(n=u.$getIndex(o.$modelValue),e=angular.isDefined(n)?u.$scope.$matches[n].label:!1),t.html((e?e:c.placeholder)+l.caretHtml)},e.$on("$destroy",function(){u&&u.destroy(),c=null,u=null})}}}]);
+"use strict";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:' ',placeholder:"Choose among the following...",maxLength:3,maxLengthHtml:"selected",iconCheckmark:"glyphicon glyphicon-ok"};this.$get=["$window","$document","$rootScope","$tooltip","$timeout",function(t,n,a,i,l){function o(t,n,a){var o={},c=angular.extend({},e,a);o=i(t,c);var u=o.$scope;u.$matches=[],u.$activeIndex=0,u.$isMultiple=c.multiple,u.$showAllNoneButtons=c.allNoneButtons&&c.multiple,u.$iconCheckmark=c.iconCheckmark,u.$activate=function(e){u.$$postDigest(function(){o.activate(e)})},u.$select=function(e){u.$$postDigest(function(){o.select(e)})},u.$isVisible=function(){return o.$isVisible()},u.$isActive=function(e){return o.$isActive(e)},u.$selectAll=function(){for(var e=0;e=u.$matches.length&&(u.$activeIndex=c.multiple?[]:0)},o.$isVisible=function(){return c.minLength&&n?u.$matches.length&&n.$viewValue.length>=c.minLength:u.$matches.length},o.$isActive=function(e){return c.multiple?-1!==u.$activeIndex.indexOf(e):u.$activeIndex===e},o.$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}},o.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),r){var t=angular.element(e.target);t.triggerHandler("click")}},o.$onKeyDown=function(e){if(/(9|13|38|40)/.test(e.keyCode)){if(e.preventDefault(),e.stopPropagation(),!c.multiple&&(13===e.keyCode||9===e.keyCode))return o.select(u.$activeIndex);38===e.keyCode&&u.$activeIndex>0?u.$activeIndex--:40===e.keyCode&&u.$activeIndex'),r.after(t)}var u=i(n.ngOptions),s=a(t,o,c),$=u.$match[7].replace(/\|.+/,"").trim();e.$watch($,function(){u.valuesFn(e,o).then(function(e){s.update(e),o.$render()})},!0),e.$watch(n.ngModel,function(){s.$updateActiveIndex(),o.$render()},!0),o.$render=function(){var e,n;c.multiple&&angular.isArray(o.$modelValue)?(e=o.$modelValue.map(function(e){return n=s.$getIndex(e),angular.isDefined(n)?s.$scope.$matches[n].label:!1}).filter(angular.isDefined),e=e.length>(c.maxLength||l.maxLength)?e.length+" "+(c.maxLengthHtml||l.maxLengthHtml):e.join(", ")):(n=s.$getIndex(o.$modelValue),e=angular.isDefined(n)?s.$scope.$matches[n].label:!1),t.html((e?e:c.placeholder)+l.caretHtml)},c.multiple&&(o.$isEmpty=function(e){return!e||0===e.length}),e.$on("$destroy",function(){s&&s.destroy(),c=null,s=null})}}}]);
//# sourceMappingURL=select.min.js.map
\ No newline at end of file
diff --git a/dist/modules/select.min.js.map b/dist/modules/select.min.js.map
old mode 100755
new mode 100644
index 462cd856c..bab67951a
--- a/dist/modules/select.min.js.map
+++ b/dist/modules/select.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["select/select.js"],"names":[],"mappings":"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","file":"select.min.js","sourcesContent":["'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: ' ',\n placeholder: 'Choose among the following...',\n maxLength: 3,\n maxLengthHtml: 'selected',\n iconCheckmark: 'glyphicon glyphicon-ok'\n };\n\n this.$get = function($window, $document, $rootScope, $tooltip) {\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 scope.$activeIndex = 0;\n scope.$isMultiple = options.multiple;\n scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n scope.$iconCheckmark = options.iconCheckmark;\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 scope.$activeIndex.sort();\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);\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 // Select with enter\n if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n return $select.select(scope.$activeIndex);\n }\n\n // Navigate with keyboard\n 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 = $select.show;\n $select.show = function() {\n _show();\n if(options.multiple) {\n $select.$element.addClass('select-multiple');\n }\n $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $select.$onKeyDown);\n }\n };\n\n var _hide = $select.hide;\n $select.hide = function() {\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', 'multiple', 'allNoneButtons', 'maxLength', 'maxLengthHtml'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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(' ');\n inputEl.after(element);\n }\n\n // Build proper ngOptions\n var parsedOptions = $parseOptions(attr.ngOptions);\n\n // Initialize select\n var select = $select(element, controller, options);\n\n // Watch ngOptions values before filtering for changes\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n scope.$watch(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 }, true);\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) + defaults.caretHtml);\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"],"sourceRoot":"/source/"}
\ No newline at end of file
+{"version":3,"sources":["select/select.js"],"names":[],"mappings":"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","file":"select.min.js","sourcesContent":["'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: ' ',\n placeholder: 'Choose among the following...',\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 scope.$activeIndex = 0;\n scope.$isMultiple = options.multiple;\n scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n scope.$iconCheckmark = options.iconCheckmark;\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 scope.$activeIndex.sort();\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);\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 // Select with enter\n if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n return $select.select(scope.$activeIndex);\n }\n\n // Navigate with keyboard\n 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 = $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 $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', 'multiple', 'allNoneButtons', 'maxLength', 'maxLengthHtml'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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(' ');\n inputEl.after(element);\n }\n\n // Build proper ngOptions\n var parsedOptions = $parseOptions(attr.ngOptions);\n\n // Initialize select\n var select = $select(element, controller, options);\n\n // Watch ngOptions values before filtering for changes\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n scope.$watch(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 }, true);\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) + 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"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/dist/modules/select.tpl.js b/dist/modules/select.tpl.js
index 388eaf9b6..9dbc32e6d 100644
--- a/dist/modules/select.tpl.js
+++ b/dist/modules/select.tpl.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -9,6 +9,6 @@
angular.module('mgcrea.ngStrap.select').run(['$templateCache', function($templateCache) {
- $templateCache.put('select/select.tpl.html', '');
+ $templateCache.put('select/select.tpl.html', '');
}]);
\ No newline at end of file
diff --git a/dist/modules/select.tpl.min.js b/dist/modules/select.tpl.min.js
index c65fda8a5..ba6ee2236 100644
--- a/dist/modules/select.tpl.min.js
+++ b/dist/modules/select.tpl.min.js
@@ -1,8 +1,8 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";angular.module("mgcrea.ngStrap.select").run(["$templateCache",function(e){e.put("select/select.tpl.html",'')}]);
\ No newline at end of file
+"use strict";angular.module("mgcrea.ngStrap.select").run(["$templateCache",function(t){t.put("select/select.tpl.html",'')}]);
\ No newline at end of file
diff --git a/dist/modules/tab.js b/dist/modules/tab.js
index 7ccb18912..637998564 100644
--- a/dist/modules/tab.js
+++ b/dist/modules/tab.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -33,7 +33,10 @@ angular.module('mgcrea.ngStrap.tab', [])
self.$panes = $scope.$panes = [];
- self.$viewChangeListeners = [];
+ // DEPRECATED: $viewChangeListeners, please use $activePaneChangeListeners
+ // Because we deprecated ngModel usage, we rename viewChangeListeners to
+ // activePaneChangeListeners to make more sense.
+ self.$activePaneChangeListeners = self.$viewChangeListeners = [];
self.$push = function(pane) {
self.$panes.push(pane);
@@ -62,7 +65,7 @@ angular.module('mgcrea.ngStrap.tab', [])
self.$panes.$active = 0;
self.$setActive = $scope.$setActive = function(value) {
self.$panes.$active = value;
- self.$viewChangeListeners.forEach(function(fn) {
+ self.$activePaneChangeListeners.forEach(function(fn) {
fn();
});
};
@@ -78,7 +81,7 @@ angular.module('mgcrea.ngStrap.tab', [])
})
- .directive('bsTabs', ["$window", "$animate", "$tab", function($window, $animate, $tab) {
+ .directive('bsTabs', ["$window", "$animate", "$tab", "$parse", function($window, $animate, $tab, $parse) {
var defaults = $tab.defaults;
@@ -95,10 +98,14 @@ angular.module('mgcrea.ngStrap.tab', [])
var ngModelCtrl = controllers[0];
var bsTabsCtrl = controllers[1];
+ // DEPRECATED: ngModel, please use bsActivePane
+ // 'ngModel' is deprecated bacause if interferes with form validation
+ // and status, so avoid using it here.
if(ngModelCtrl) {
+ console.warn('Usage of ngModel is deprecated, please use bsActivePane instead!');
// Update the modelValue following
- bsTabsCtrl.$viewChangeListeners.push(function() {
+ bsTabsCtrl.$activePaneChangeListeners.push(function() {
ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);
});
@@ -111,6 +118,21 @@ angular.module('mgcrea.ngStrap.tab', [])
}
+ if (attrs.bsActivePane) {
+ // adapted from angularjs ngModelController bindings
+ // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730
+ var parsedBsActivePane = $parse(attrs.bsActivePane);
+
+ // Update bsActivePane value with change
+ bsTabsCtrl.$activePaneChangeListeners.push(function() {
+ parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);
+ });
+
+ // watch bsActivePane for value changes
+ scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {
+ bsTabsCtrl.$setActive(newValue * 1);
+ }, true);
+ }
}
};
@@ -153,7 +175,7 @@ angular.module('mgcrea.ngStrap.tab', [])
$animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);
}
- bsTabsCtrl.$viewChangeListeners.push(function() {
+ bsTabsCtrl.$activePaneChangeListeners.push(function() {
render();
});
render();
diff --git a/dist/modules/tab.min.js b/dist/modules/tab.min.js
index bfd1850e9..fb0444de4 100644
--- a/dist/modules/tab.min.js
+++ b/dist/modules/tab.min.js
@@ -1,9 +1,9 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";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 s=this;s.$options=angular.copy(e),angular.forEach(["animation","navClass","activeClass"],function(e){angular.isDefined(a[e])&&(s.$options[e]=a[e])}),t.$navClass=s.$options.navClass,t.$activeClass=s.$options.activeClass,s.$panes=t.$panes=[],s.$viewChangeListeners=[],s.$push=function(e){s.$panes.push(e)},s.$remove=function(e){var t=s.$panes.indexOf(e),n=s.$panes.$active;s.$panes.splice(t,1),n>t?n--:t===n&&n===s.$panes.length&&n--,s.$setActive(n)},s.$panes.$active=0,s.$setActive=t.$setActive=function(e){s.$panes.$active=e,s.$viewChangeListeners.forEach(function(e){e()})}};this.$get=function(){var n={};return n.defaults=e,n.controller=t,n}}).directive("bsTabs",["$window","$animate","$tab",function(e,t,n){var a=n.defaults;return{require:["?ngModel","bsTabs"],transclude:!0,scope:!0,controller:["$scope","$element","$attrs",n.controller],templateUrl:function(e,t){return t.template||a.template},link:function(e,t,n,a){var s=a[0],i=a[1];s&&(i.$viewChangeListeners.push(function(){s.$setViewValue(i.$panes.$active)}),s.$formatters.push(function(e){return i.$setActive(1*e),e}))}}}]).directive("bsPane",["$window","$animate","$sce",function(e,t,n){return{require:["^?ngModel","^bsTabs"],scope:!0,link:function(e,a,s,i){function o(){var n=r.$panes.indexOf(e),s=r.$panes.$active;t[n===s?"addClass":"removeClass"](a,r.$options.activeClass)}var r=(i[0],i[1]);a.addClass("tab-pane"),s.$observe("title",function(t){e.title=n.trustAsHtml(t)}),r.$options.animation&&a.addClass(r.$options.animation),r.$push(e),e.$on("$destroy",function(){r.$remove(e)}),r.$viewChangeListeners.push(function(){o()}),o()}}}]);
+"use strict";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"},a=this.controller=function(a,n,t){var s=this;s.$options=angular.copy(e),angular.forEach(["animation","navClass","activeClass"],function(e){angular.isDefined(t[e])&&(s.$options[e]=t[e])}),a.$navClass=s.$options.navClass,a.$activeClass=s.$options.activeClass,s.$panes=a.$panes=[],s.$activePaneChangeListeners=s.$viewChangeListeners=[],s.$push=function(e){s.$panes.push(e)},s.$remove=function(e){var a=s.$panes.indexOf(e),n=s.$panes.$active;s.$panes.splice(a,1),n>a?n--:a===n&&n===s.$panes.length&&n--,s.$setActive(n)},s.$panes.$active=0,s.$setActive=a.$setActive=function(e){s.$panes.$active=e,s.$activePaneChangeListeners.forEach(function(e){e()})}};this.$get=function(){var n={};return n.defaults=e,n.controller=a,n}}).directive("bsTabs",["$window","$animate","$tab","$parse",function(e,a,n,t){var s=n.defaults;return{require:["?ngModel","bsTabs"],transclude:!0,scope:!0,controller:["$scope","$element","$attrs",n.controller],templateUrl:function(e,a){return a.template||s.template},link:function(e,a,n,s){var i=s[0],o=s[1];if(i&&(console.warn("Usage of ngModel is deprecated, please use bsActivePane instead!"),o.$activePaneChangeListeners.push(function(){i.$setViewValue(o.$panes.$active)}),i.$formatters.push(function(e){return o.$setActive(1*e),e})),n.bsActivePane){var c=t(n.bsActivePane);o.$activePaneChangeListeners.push(function(){c.assign(e,o.$panes.$active)}),e.$watch(n.bsActivePane,function(e){o.$setActive(1*e)},!0)}}}}]).directive("bsPane",["$window","$animate","$sce",function(e,a,n){return{require:["^?ngModel","^bsTabs"],scope:!0,link:function(e,t,s,i){function o(){var n=c.$panes.indexOf(e),s=c.$panes.$active;a[n===s?"addClass":"removeClass"](t,c.$options.activeClass)}var c=(i[0],i[1]);t.addClass("tab-pane"),s.$observe("title",function(a){e.title=n.trustAsHtml(a)}),c.$options.animation&&t.addClass(c.$options.animation),c.$push(e),e.$on("$destroy",function(){c.$remove(e)}),c.$activePaneChangeListeners.push(function(){o()}),o()}}}]);
//# sourceMappingURL=tab.min.js.map
\ No newline at end of file
diff --git a/dist/modules/tab.min.js.map b/dist/modules/tab.min.js.map
old mode 100755
new mode 100644
index a5518c7ec..e0575365e
--- a/dist/modules/tab.min.js.map
+++ b/dist/modules/tab.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["tab/tab.js"],"names":[],"mappings":"qBASM,OAAA,kCAEF,OAAA,WAEA,GAAA,GAAA,KAAA,UACE,UAAA,sCAEA,SAAA,WACA,YAAA,UAGA,EAAA,KAAA,WAAA,SAAA,EAAA,EAAA,aAIA,GAAA,SAAA,QAAA,KAAA,sEAEA,QAAA,UAAA,EAAA,MAAA,EAAA,SAAA,GAAA,EAAA,MAIA,EAAA,UAAA,EAAA,SAAA,WACE,aAAA,EAAA,SAAA,mCAIA,4CAGA,EAAA,OAAA,KAAA,MAGA,QAAA,SAAA,MACE,GAAA,EAAA,OAAA,QAAA,GACA,EAAA,EAAA,OAAA,OAGF,GAAA,OAAA,OAAA,EAAA,GAEE,EAAA,EAGF,gCAKA,MAEE,WAAA,uBAIN,EAAA,WAAA,EAAA,WAAA,SAAA,sBAEA,EAAA,qBAAA,QAAA,SAAA,GACE,OAMJ,MAAA,KAAA,mBAIE,OAFF,GAAA,SAAkB,iBAEhB,eAKE,UAAA,UAAA,WAAA,OAAA,SAAA,EAAA,EAAA,MAEA,GAAA,EAAA,gBAGA,SAAA,WAAA,+BAEE,cACA,SAAA,WAAA,SAAA,EAAA,sCAEA,MAAA,GAAA,UAAA,EAAA,eAEE,SAAA,EAAA,EAAA,EAAA,MAEE,GAAA,EAAA,GACF,EAAA,EAAA,EAEA,OAGE,qBAAA,KAAA,WACA,EAAA,cAAA,EAAA,OAAA,gDAMR,GAAA,WAAA,EAAA,uBAWI,UAAA,UAAA,WAAA,OAAA,SAAA,EAAA,EAAA,mBAGA,YAAA,kBACA,iCA2BE,KACF,GAAA,GAAA,EAAA,OAAA,QAAA,GACA,EAAA,EAAA,OAAA,oEA1BA,GACE,IADF,EAAA,GACE,EAAA,GAGF,GAAA,SAAA,YAGA,EAAA,SAAA,QAAA,SAAA,8BAKA,EAAA,SAAA,WACA,EAAA,SAAA,EAAA,SAAA,WAIA,EAAA,MAAA,KAGE,IAAA,WAAA,WACF,EAAA,QAAA,4CAUL","file":"tab.min.js","sourcesContent":["'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 self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var activeIndex = self.$panes.$active;\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 self.$setActive(activeIndex);\n };\n\n self.$panes.$active = 0;\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\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) {\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 if(ngModelCtrl) {\n\n // Update the modelValue following\n bsTabsCtrl.$viewChangeListeners.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 * 1);\n return modelValue;\n });\n\n }\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 // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\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 var active = bsTabsCtrl.$panes.$active;\n $animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n"],"sourceRoot":"/source/"}
\ No newline at end of file
+{"version":3,"sources":["tab/tab.js"],"names":[],"mappings":"qBASM,OAAA,kCAEF,OAAA,WAEA,GAAA,GAAA,KAAA,UACE,UAAA,sCAEA,SAAA,WACA,YAAA,UAGA,EAAA,KAAA,WAAA,SAAA,EAAA,EAAA,aAIA,GAAA,SAAA,QAAA,KAAA,sEAEA,QAAA,UAAA,EAAA,MAAA,EAAA,SAAA,GAAA,EAAA,MAIA,EAAA,UAAA,EAAA,SAAA,SACA,EAAA,aAAA,EAAA,SAAA,YAEA,EAAA,OAAA,EAAA,YAKE,2BAAA,EAAA,4CAGA,EAAA,OAAA,KAAA,MAGA,QAAA,SAAA,MACE,GAAA,EAAA,OAAA,QAAA,GACA,EAAA,EAAA,OAAA,OAGF,GAAA,OAAA,OAAA,EAAA,GAEE,EAAA,EAGF,gCAKA,MAEE,WAAA,uBAIN,EAAA,WAAA,EAAA,WAAA,SAAA,sBAEA,EAAA,2BAAA,QAAA,SAAA,GACE,OAMJ,MAAA,KAAA,mBAIE,OAFF,GAAA,SAAkB,iBAEhB,eAKE,UAAA,UAAA,WAAA,OAAA,SAAA,SAAA,EAAA,EAAA,EAAA,MAEA,GAAA,EAAA,gBAGA,SAAA,WAAA,+BAEE,cACA,SAAA,WAAA,SAAA,EAAA,sCAEA,MAAA,GAAA,UAAA,EAAA,eAEA,SAAA,EAAA,EAAA,EAAA,MAEE,GAAA,EAAA,iBAOA,QAAA,KAAA,sEAGE,2BAAA,KAAA,WACA,EAAA,cAAA,EAAA,OAAA,0CAOF,MADA,GAAA,WAAA,EAAA,GACA,KAKE,EAAA,aAAA,CAGF,GAAA,GAAA,EAAA,EAAA,aAGA,GAAA,2BAAA,KAAA,WACF,EAAA,OAAA,EAAA,EAAA,OAAA,WAIL,EAAA,OAAA,EAAA,aAAA,SAAA,uBAED,mBAOM,UAAA,UAAA,WAAA,OAAA,SAAA,EAAA,EAAA,mBAGA,YAAA,kBACA,iCA2BE,KACF,GAAA,GAAA,EAAA,OAAA,QAAA,GACA,EAAA,EAAA,OAAA,oEA1BA,GACE,IADF,EAAA,GACE,EAAA,GAGF,GAAA,SAAA,YAGA,EAAA,SAAA,QAAA,SAAA,8BAKA,EAAA,SAAA,WACA,EAAA,SAAA,EAAA,SAAA,WAIA,EAAA,MAAA,KAGE,IAAA,WAAA,WACF,EAAA,QAAA,kDAUL","file":"tab.min.js","sourcesContent":["'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 // DEPRECATED: $viewChangeListeners, please use $activePaneChangeListeners\n // Because we deprecated ngModel usage, we rename viewChangeListeners to \n // activePaneChangeListeners to make more sense.\n self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var activeIndex = self.$panes.$active;\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 self.$setActive(activeIndex);\n };\n\n self.$panes.$active = 0;\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$activePaneChangeListeners.forEach(function(fn) {\n fn();\n });\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 // DEPRECATED: ngModel, please use bsActivePane\n // 'ngModel' is deprecated bacause if interferes with form validation\n // and status, so avoid using it here.\n if(ngModelCtrl) {\n console.warn('Usage of ngModel is deprecated, please use bsActivePane instead!');\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 * 1);\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 * 1);\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 // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\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 var active = bsTabsCtrl.$panes.$active;\n $animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/dist/modules/tab.tpl.js b/dist/modules/tab.tpl.js
index 6591415ac..d8c733257 100644
--- a/dist/modules/tab.tpl.js
+++ b/dist/modules/tab.tpl.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -9,6 +9,6 @@
angular.module('mgcrea.ngStrap.tab').run(['$templateCache', function($templateCache) {
- $templateCache.put('tab/tab.tpl.html', '
');
+ $templateCache.put('tab/tab.tpl.html', '
');
}]);
\ No newline at end of file
diff --git a/dist/modules/tab.tpl.min.js b/dist/modules/tab.tpl.min.js
index 49f3bf069..3cb875f14 100644
--- a/dist/modules/tab.tpl.min.js
+++ b/dist/modules/tab.tpl.min.js
@@ -1,8 +1,8 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";angular.module("mgcrea.ngStrap.tab").run(["$templateCache",function(a){a.put("tab/tab.tpl.html",'
')}]);
\ No newline at end of file
+"use strict";angular.module("mgcrea.ngStrap.tab").run(["$templateCache",function(a){a.put("tab/tab.tpl.html",'
')}]);
\ No newline at end of file
diff --git a/dist/modules/timepicker.js b/dist/modules/timepicker.js
index ad70bc704..a64f36e8f 100644
--- a/dist/modules/timepicker.js
+++ b/dist/modules/timepicker.js
@@ -1,13 +1,16 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
'use strict';
-angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser', 'mgcrea.ngStrap.tooltip'])
+angular.module('mgcrea.ngStrap.timepicker', [
+ 'mgcrea.ngStrap.helpers.dateParser',
+ 'mgcrea.ngStrap.helpers.dateFormatter',
+ 'mgcrea.ngStrap.tooltip'])
.provider('$timepicker', function() {
@@ -37,12 +40,12 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
arrowBehavior: 'pager'
};
- this.$get = ["$window", "$document", "$rootScope", "$sce", "$locale", "dateFilter", "$tooltip", "$timeout", function($window, $document, $rootScope, $sce, $locale, dateFilter, $tooltip, $timeout) {
+ this.$get = ["$window", "$document", "$rootScope", "$sce", "$dateFormatter", "$tooltip", "$timeout", function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {
var bodyEl = angular.element($window.document.body);
var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
var isTouch = ('createTouch' in $window.document) && isNative;
- if(!defaults.lang) defaults.lang = $locale.id;
+ if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();
function timepickerFactory(element, controller, config) {
@@ -51,14 +54,24 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
var options = $timepicker.$options;
var scope = $timepicker.$scope;
+ var lang = options.lang;
+ var formatDate = function(date, format) {
+ return $dateFormatter.formatDate(date, format, lang);
+ };
+
// View vars
var selectedIndex = 0;
var startDate = controller.$dateValue || new Date();
var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};
- var format = $locale.DATETIME_FORMATS[options.timeFormat] || options.timeFormat;
- var formats = /(h+)([:\.])?(m+)[ ]?(a?)/i.exec(format).slice(1);
+ var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);
+
+ var hoursFormat = $dateFormatter.hoursFormat(format),
+ timeSeparator = $dateFormatter.timeSeparator(format),
+ minutesFormat = $dateFormatter.minutesFormat(format),
+ showAM = $dateFormatter.showAM(format);
+
scope.$iconUp = options.iconUp;
scope.$iconDown = options.iconDown;
@@ -118,12 +131,12 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
var hours = [], hour;
for(i = 0; i < options.length; i++) {
hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);
- hours.push({date: hour, label: dateFilter(hour, formats[0]), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});
+ hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});
}
var minutes = [], minute;
for(i = 0; i < options.length; i++) {
minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);
- minutes.push({date: minute, label: dateFilter(minute, formats[2]), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});
+ minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});
}
var rows = [];
@@ -131,9 +144,9 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
rows.push([hours[i], minutes[i]]);
}
scope.rows = rows;
- scope.showAM = !!formats[3];
+ scope.showAM = showAM;
scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;
- scope.timeSeparator = formats[1];
+ scope.timeSeparator = timeSeparator;
$timepicker.$isBuilt = true;
};
@@ -166,8 +179,8 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
$timepicker.$setTimeByStep = function(value, index) {
var newDate = new Date($timepicker.$date);
- var hours = newDate.getHours(), hoursLength = dateFilter(newDate, 'h').length;
- var minutes = newDate.getMinutes(), minutesLength = dateFilter(newDate, 'mm').length;
+ var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;
+ var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;
if (index === 0) {
newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));
}
@@ -213,10 +226,10 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
// Navigate with keyboard
var newDate = new Date($timepicker.$date);
- var hours = newDate.getHours(), hoursLength = dateFilter(newDate, 'h').length;
- var minutes = newDate.getMinutes(), minutesLength = dateFilter(newDate, 'mm').length;
+ var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;
+ var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;
var lateralMove = /(37|39)/.test(evt.keyCode);
- var count = 2 + !!formats[3] * 1;
+ var count = 2 + showAM * 1;
// Navigate indexes (left, right)
if (lateralMove) {
@@ -229,10 +242,14 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
if(selectedIndex === 0) {
if(evt.keyCode === 38) newDate.setHours(hours - parseInt(options.hourStep, 10));
else if(evt.keyCode === 40) newDate.setHours(hours + parseInt(options.hourStep, 10));
+ // re-calculate hours length because we have changed hours value
+ hoursLength = formatDate(newDate, hoursFormat).length;
selectRange = [0, hoursLength];
} else if(selectedIndex === 1) {
if(evt.keyCode === 38) newDate.setMinutes(minutes - parseInt(options.minuteStep, 10));
else if(evt.keyCode === 40) newDate.setMinutes(minutes + parseInt(options.minuteStep, 10));
+ // re-calculate minutes length because we have changes minutes value
+ minutesLength = formatDate(newDate, minutesFormat).length;
selectRange = [hoursLength + 1, hoursLength + 1 + minutesLength];
} else if(selectedIndex === 2) {
if(!lateralMove) $timepicker.switchMeridian();
@@ -291,10 +308,14 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
var _show = $timepicker.show;
$timepicker.show = function() {
_show();
- $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);
- if(options.keyboard) {
- element.on('keydown', $timepicker.$onKeyDown);
- }
+ // use timeout to hookup the events to prevent
+ // event bubbling from being processed imediately.
+ $timeout(function() {
+ $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);
+ if(options.keyboard) {
+ element.on('keydown', $timepicker.$onKeyDown);
+ }
+ }, 0, false);
};
var _hide = $timepicker.hide;
@@ -319,7 +340,7 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
})
- .directive('bsTimepicker', ["$window", "$parse", "$q", "$locale", "dateFilter", "$timepicker", "$dateParser", function($window, $parse, $q, $locale, dateFilter, $timepicker, $dateParser) {
+ .directive('bsTimepicker', ["$window", "$parse", "$q", "$dateFormatter", "$dateParser", "$timepicker", function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {
var defaults = $timepicker.defaults;
var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);
@@ -348,8 +369,13 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
var timepicker = $timepicker(element, controller, options);
options = timepicker.$options;
+ var lang = options.lang;
+ var formatDate = function(date, format) {
+ return $dateFormatter.formatDate(date, format, lang);
+ };
+
// Initialize parser
- var dateParser = $dateParser({format: options.timeFormat, lang: options.lang});
+ var dateParser = $dateParser({format: options.timeFormat, lang: lang});
// Observe attributes for changes
angular.forEach(['minTime', 'maxTime'], function(key) {
@@ -387,18 +413,23 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
// console.warn('$parser("%s"): viewValue=%o', element.attr('ng-model'), viewValue);
// Null values should correctly reset the model value & validity
if(!viewValue) {
+ // BREAKING CHANGE:
+ // return null (not undefined) when input value is empty, so angularjs 1.3
+ // ngModelController can go ahead and run validators, like ngRequired
controller.$setValidity('date', true);
- return;
+ return null;
}
var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);
if(!parsedTime || isNaN(parsedTime.getTime())) {
controller.$setValidity('date', false);
+ // return undefined, causes ngModelController to
+ // invalidate model value
return;
} else {
validateAgainstMinMaxTime(parsedTime);
}
if(options.timeType === 'string') {
- return dateFilter(parsedTime, options.modelTimeFormat || options.timeFormat);
+ return formatDate(parsedTime, options.modelTimeFormat || options.timeFormat);
} else if(options.timeType === 'number') {
return controller.$dateValue.getTime();
} else if(options.timeType === 'iso') {
@@ -434,7 +465,7 @@ angular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser'
};
function getTimeFormattedString() {
- return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : dateFilter(controller.$dateValue, options.timeFormat);
+ return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);
}
// Garbage collection
diff --git a/dist/modules/timepicker.min.js b/dist/modules/timepicker.min.js
index ed9d3aa11..1948aa422 100644
--- a/dist/modules/timepicker.min.js
+++ b/dist/modules/timepicker.min.js
@@ -1,9 +1,9 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";angular.module("mgcrea.ngStrap.timepicker",["mgcrea.ngStrap.helpers.dateParser","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",modelTimeFormat:null,autoclose:!1,minTime:-1/0,maxTime:+1/0,length:5,hourStep:1,minuteStep:5,iconUp:"glyphicon glyphicon-chevron-up",iconDown:"glyphicon glyphicon-chevron-down",arrowBehavior:"pager"};this.$get=["$window","$document","$rootScope","$sce","$locale","dateFilter","$tooltip","$timeout",function(t,n,a,i,o,r,u,s){function l(t,n,a){function i(e,n){if(t[0].createTextRange){var a=t[0].createTextRange();a.collapse(!0),a.moveStart("character",e),a.moveEnd("character",n),a.select()}else t[0].setSelectionRange?t[0].setSelectionRange(e,n):angular.isUndefined(t[0].selectionStart)&&(t[0].selectionStart=e,t[0].selectionEnd=n)}function l(){t[0].focus()}var c=u(t,angular.extend({},e,a)),g=a.scope,$=c.$options,p=c.$scope,h=0,f=n.$dateValue||new Date,v={hour:f.getHours(),meridian:f.getHours()<12,minute:f.getMinutes(),second:f.getSeconds(),millisecond:f.getMilliseconds()},w=o.DATETIME_FORMATS[$.timeFormat]||$.timeFormat,y=/(h+)([:\.])?(m+)[ ]?(a?)/i.exec(w).slice(1);p.$iconUp=$.iconUp,p.$iconDown=$.iconDown,p.$select=function(e,t){c.select(e,t)},p.$moveIndex=function(e,t){c.$moveIndex(e,t)},p.$switchMeridian=function(e){c.switchMeridian(e)},c.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())?(c.$date=e,angular.extend(v,{hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}),c.$build()):c.$isBuilt||c.$build()},c.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()),n.$setViewValue(angular.copy(n.$dateValue)),n.$render(),$.autoclose&&!a&&s(function(){c.hide(!0)})},c.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()}},c.$build=function(){var e,t,n=p.midIndex=parseInt($.length/2,10),a=[];for(e=0;e<$.length;e++)t=new Date(1970,0,1,v.hour-(n-e)*$.hourStep),a.push({date:t,label:r(t,y[0]),selected:c.$date&&c.$isSelected(t,0),disabled:c.$isDisabled(t,0)});var i,o=[];for(e=0;e<$.length;e++)i=new Date(1970,0,1,0,v.minute-(n-e)*$.minuteStep),o.push({date:i,label:r(i,y[2]),selected:c.$date&&c.$isSelected(i,1),disabled:c.$isDisabled(i,1)});var u=[];for(e=0;e<$.length;e++)u.push([a[e],o[e]]);p.rows=u,p.showAM=!!y[3],p.isAM=(c.$date||a[n].date).getHours()<12,p.timeSeparator=y[1],c.$isBuilt=!0},c.$isSelected=function(e,t){return c.$date?0===t?e.getHours()===c.$date.getHours():1===t?e.getMinutes()===c.$date.getMinutes():void 0:!1},c.$isDisabled=function(e,t){var n;return 0===t?n=e.getTime()+6e4*v.minute:1===t&&(n=e.getTime()+36e5*v.hour),n<1*$.minTime||n>1*$.maxTime},p.$arrowAction=function(e,t){"picker"===$.arrowBehavior?c.$setTimeByStep(e,t):c.$moveIndex(e,t)},c.$setTimeByStep=function(e,t){{var n=new Date(c.$date),a=n.getHours(),i=(r(n,"h").length,n.getMinutes());r(n,"mm").length}0===t?n.setHours(a-parseInt($.hourStep,10)*e):n.setMinutes(i-parseInt($.minuteStep,10)*e),c.select(n,t,!0)},c.$moveIndex=function(e,t){var n;0===t?(n=new Date(1970,0,1,v.hour+e*$.length,v.minute),angular.extend(v,{hour:n.getHours()})):1===t&&(n=new Date(1970,0,1,v.hour,v.minute+e*$.length*$.minuteStep),angular.extend(v,{minute:n.getMinutes()})),c.$build()},c.$onMouseDown=function(e){if("input"!==e.target.nodeName.toLowerCase()&&e.preventDefault(),e.stopPropagation(),m){var t=angular.element(e.target);"button"!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler("click")}},c.$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 c.hide(!0);var t=new Date(c.$date),n=t.getHours(),a=r(t,"h").length,o=t.getMinutes(),u=r(t,"mm").length,s=/(37|39)/.test(e.keyCode),l=2+1*!!y[3];s&&(37===e.keyCode?h=1>h?l-1:h-1:39===e.keyCode&&(h=l-1>h?h+1:0));var d=[0,a];0===h?(38===e.keyCode?t.setHours(n-parseInt($.hourStep,10)):40===e.keyCode&&t.setHours(n+parseInt($.hourStep,10)),d=[0,a]):1===h?(38===e.keyCode?t.setMinutes(o-parseInt($.minuteStep,10)):40===e.keyCode&&t.setMinutes(o+parseInt($.minuteStep,10)),d=[a+1,a+1+u]):2===h&&(s||c.switchMeridian(),d=[a+1+u+1,a+1+u+3]),c.select(t,h,!0),i(d[0],d[1]),g.$digest()}};var T=c.init;c.init=function(){return d&&$.useNative?(t.prop("type","time"),void t.css("-webkit-appearance","textfield")):(m&&(t.prop("type","text"),t.attr("readonly","true"),t.on("click",l)),void T())};var D=c.destroy;c.destroy=function(){d&&$.useNative&&t.off("click",l),D()};var S=c.show;c.show=function(){S(),c.$element.on(m?"touchstart":"mousedown",c.$onMouseDown),$.keyboard&&t.on("keydown",c.$onKeyDown)};var V=c.hide;return c.hide=function(e){c.$isShown&&(c.$element.off(m?"touchstart":"mousedown",c.$onMouseDown),$.keyboard&&t.off("keydown",c.$onKeyDown),V(e))},c}var d=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),m="createTouch"in t.document&&d;return e.lang||(e.lang=o.id),l.defaults=e,l}]}).directive("bsTimepicker",["$window","$parse","$q","$locale","dateFilter","$timepicker","$dateParser",function(e,t,n,a,i,o,r){{var u=o.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,a){function l(e){if(angular.isDate(e)){var t=isNaN(m.minTime)||new Date(e.getTime()).setFullYear(1970,0,1)>=m.minTime,n=isNaN(m.maxTime)||new Date(e.getTime()).setFullYear(1970,0,1)<=m.maxTime,i=t&&n;a.$setValidity("date",i),a.$setValidity("min",t),a.$setValidity("max",n),i&&(a.$dateValue=e)}}function d(){return!a.$dateValue||isNaN(a.$dateValue.getTime())?"":i(a.$dateValue,m.timeFormat)}var m={scope:e,controller:a};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","autoclose","timeType","timeFormat","modelTimeFormat","useNative","hourStep","minuteStep","length","arrowBehavior","iconUp","iconDown"],function(e){angular.isDefined(n[e])&&(m[e]=n[e])}),n.bsShow&&e.$watch(n.bsShow,function(e){c&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(timepicker),?/i)),e===!0?c.show():c.hide())}),s&&(m.useNative||u.useNative)&&(m.timeFormat="HH:mm");var c=o(t,a,m);m=c.$options;var g=r({format:m.timeFormat,lang:m.lang});angular.forEach(["minTime","maxTime"],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){c.$options[e]=g.getTimeForAttribute(e,t),!isNaN(c.$options[e])&&c.$build(),l(a.$dateValue)})}),e.$watch(n.ngModel,function(){c.update(a.$dateValue)},!0),a.$parsers.unshift(function(e){if(!e)return void a.$setValidity("date",!0);var t=angular.isDate(e)?e:g.parse(e,a.$dateValue);return!t||isNaN(t.getTime())?void a.$setValidity("date",!1):(l(t),"string"===m.timeType?i(t,m.modelTimeFormat||m.timeFormat):"number"===m.timeType?a.$dateValue.getTime():"iso"===m.timeType?a.$dateValue.toISOString():new Date(a.$dateValue))}),a.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:"string"===m.timeType?g.parse(e,null,m.modelTimeFormat):new Date(e),a.$dateValue=t,d()}),a.$render=function(){t.val(d())},e.$on("$destroy",function(){c&&c.destroy(),m=null,c=null})}}}]);
+"use strict";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",modelTimeFormat:null,autoclose:!1,minTime:-1/0,maxTime:+1/0,length:5,hourStep:1,minuteStep:5,iconUp:"glyphicon glyphicon-chevron-up",iconDown:"glyphicon glyphicon-chevron-down",arrowBehavior:"pager"};this.$get=["$window","$document","$rootScope","$sce","$dateFormatter","$tooltip","$timeout",function(t,a,n,i,o,r,u){function s(t,a,n){function i(e,a){if(t[0].createTextRange){var n=t[0].createTextRange();n.collapse(!0),n.moveStart("character",e),n.moveEnd("character",a),n.select()}else t[0].setSelectionRange?t[0].setSelectionRange(e,a):angular.isUndefined(t[0].selectionStart)&&(t[0].selectionStart=e,t[0].selectionEnd=a)}function s(){t[0].focus()}var m=r(t,angular.extend({},e,n)),c=n.scope,g=m.$options,p=m.$scope,$=g.lang,f=function(e,t){return o.formatDate(e,t,$)},h=0,w=a.$dateValue||new Date,v={hour:w.getHours(),meridian:w.getHours()<12,minute:w.getMinutes(),second:w.getSeconds(),millisecond:w.getMilliseconds()},y=o.getDatetimeFormat(g.timeFormat,$),D=o.hoursFormat(y),T=o.timeSeparator(y),S=o.minutesFormat(y),V=o.showAM(y);p.$iconUp=g.iconUp,p.$iconDown=g.iconDown,p.$select=function(e,t){m.select(e,t)},p.$moveIndex=function(e,t){m.$moveIndex(e,t)},p.$switchMeridian=function(e){m.switchMeridian(e)},m.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())?(m.$date=e,angular.extend(v,{hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}),m.$build()):m.$isBuilt||m.$build()},m.select=function(e,t,n){(!a.$dateValue||isNaN(a.$dateValue.getTime()))&&(a.$dateValue=new Date(1970,0,1)),angular.isDate(e)||(e=new Date(e)),0===t?a.$dateValue.setHours(e.getHours()):1===t&&a.$dateValue.setMinutes(e.getMinutes()),a.$setViewValue(angular.copy(a.$dateValue)),a.$render(),g.autoclose&&!n&&u(function(){m.hide(!0)})},m.switchMeridian=function(e){if(a.$dateValue&&!isNaN(a.$dateValue.getTime())){var t=(e||a.$dateValue).getHours();a.$dateValue.setHours(12>t?t+12:t-12),a.$setViewValue(angular.copy(a.$dateValue)),a.$render()}},m.$build=function(){var e,t,a=p.midIndex=parseInt(g.length/2,10),n=[];for(e=0;e1*g.maxTime},p.$arrowAction=function(e,t){"picker"===g.arrowBehavior?m.$setTimeByStep(e,t):m.$moveIndex(e,t)},m.$setTimeByStep=function(e,t){{var a=new Date(m.$date),n=a.getHours(),i=(f(a,D).length,a.getMinutes());f(a,S).length}0===t?a.setHours(n-parseInt(g.hourStep,10)*e):a.setMinutes(i-parseInt(g.minuteStep,10)*e),m.select(a,t,!0)},m.$moveIndex=function(e,t){var a;0===t?(a=new Date(1970,0,1,v.hour+e*g.length,v.minute),angular.extend(v,{hour:a.getHours()})):1===t&&(a=new Date(1970,0,1,v.hour,v.minute+e*g.length*g.minuteStep),angular.extend(v,{minute:a.getMinutes()})),m.$build()},m.$onMouseDown=function(e){if("input"!==e.target.nodeName.toLowerCase()&&e.preventDefault(),e.stopPropagation(),d){var t=angular.element(e.target);"button"!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler("click")}},m.$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 m.hide(!0);var t=new Date(m.$date),a=t.getHours(),n=f(t,D).length,o=t.getMinutes(),r=f(t,S).length,u=/(37|39)/.test(e.keyCode),s=2+1*V;u&&(37===e.keyCode?h=1>h?s-1:h-1:39===e.keyCode&&(h=s-1>h?h+1:0));var l=[0,n];0===h?(38===e.keyCode?t.setHours(a-parseInt(g.hourStep,10)):40===e.keyCode&&t.setHours(a+parseInt(g.hourStep,10)),n=f(t,D).length,l=[0,n]):1===h?(38===e.keyCode?t.setMinutes(o-parseInt(g.minuteStep,10)):40===e.keyCode&&t.setMinutes(o+parseInt(g.minuteStep,10)),r=f(t,S).length,l=[n+1,n+1+r]):2===h&&(u||m.switchMeridian(),l=[n+1+r+1,n+1+r+3]),m.select(t,h,!0),i(l[0],l[1]),c.$digest()}};var k=m.init;m.init=function(){return l&&g.useNative?(t.prop("type","time"),void t.css("-webkit-appearance","textfield")):(d&&(t.prop("type","text"),t.attr("readonly","true"),t.on("click",s)),void k())};var b=m.destroy;m.destroy=function(){l&&g.useNative&&t.off("click",s),b()};var M=m.show;m.show=function(){M(),u(function(){m.$element.on(d?"touchstart":"mousedown",m.$onMouseDown),g.keyboard&&t.on("keydown",m.$onKeyDown)},0,!1)};var N=m.hide;return m.hide=function(e){m.$isShown&&(m.$element.off(d?"touchstart":"mousedown",m.$onMouseDown),g.keyboard&&t.off("keydown",m.$onKeyDown),N(e))},m}var l=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),d="createTouch"in t.document&&l;return e.lang||(e.lang=o.getDefaultLocale()),s.defaults=e,s}]}).directive("bsTimepicker",["$window","$parse","$q","$dateFormatter","$dateParser","$timepicker",function(e,t,a,n,i,o){{var r=o.defaults,u=/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent);e.requestAnimationFrame||e.setTimeout}return{restrict:"EAC",require:"ngModel",link:function(e,t,a,s){function l(e){if(angular.isDate(e)){var t=isNaN(m.minTime)||new Date(e.getTime()).setFullYear(1970,0,1)>=m.minTime,a=isNaN(m.maxTime)||new Date(e.getTime()).setFullYear(1970,0,1)<=m.maxTime,n=t&&a;s.$setValidity("date",n),s.$setValidity("min",t),s.$setValidity("max",a),n&&(s.$dateValue=e)}}function d(){return!s.$dateValue||isNaN(s.$dateValue.getTime())?"":p(s.$dateValue,m.timeFormat)}var m={scope:e,controller:s};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","autoclose","timeType","timeFormat","modelTimeFormat","useNative","hourStep","minuteStep","length","arrowBehavior","iconUp","iconDown"],function(e){angular.isDefined(a[e])&&(m[e]=a[e])}),a.bsShow&&e.$watch(a.bsShow,function(e){c&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(timepicker),?/i)),e===!0?c.show():c.hide())}),u&&(m.useNative||r.useNative)&&(m.timeFormat="HH:mm");var c=o(t,s,m);m=c.$options;var g=m.lang,p=function(e,t){return n.formatDate(e,t,g)},$=i({format:m.timeFormat,lang:g});angular.forEach(["minTime","maxTime"],function(e){angular.isDefined(a[e])&&a.$observe(e,function(t){c.$options[e]=$.getTimeForAttribute(e,t),!isNaN(c.$options[e])&&c.$build(),l(s.$dateValue)})}),e.$watch(a.ngModel,function(){c.update(s.$dateValue)},!0),s.$parsers.unshift(function(e){if(!e)return s.$setValidity("date",!0),null;var t=angular.isDate(e)?e:$.parse(e,s.$dateValue);return!t||isNaN(t.getTime())?void s.$setValidity("date",!1):(l(t),"string"===m.timeType?p(t,m.modelTimeFormat||m.timeFormat):"number"===m.timeType?s.$dateValue.getTime():"iso"===m.timeType?s.$dateValue.toISOString():new Date(s.$dateValue))}),s.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:"string"===m.timeType?$.parse(e,null,m.modelTimeFormat):new Date(e),s.$dateValue=t,d()}),s.$render=function(){t.val(d())},e.$on("$destroy",function(){c&&c.destroy(),m=null,c=null})}}}]);
//# sourceMappingURL=timepicker.min.js.map
\ No newline at end of file
diff --git a/dist/modules/timepicker.min.js.map b/dist/modules/timepicker.min.js.map
old mode 100755
new mode 100644
index 5009468d1..ceabab678
--- a/dist/modules/timepicker.min.js.map
+++ b/dist/modules/timepicker.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["timepicker/timepicker.js"],"names":[],"mappings":"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","file":"timepicker.min.js","sourcesContent":["'use strict';\n\nangular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser', 'mgcrea.ngStrap.tooltip'])\n\n .provider('$timepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\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 modelTimeFormat: null,\n autoclose: false,\n minTime: -Infinity,\n maxTime: +Infinity,\n length: 5,\n hourStep: 1,\n minuteStep: 5,\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, $locale, dateFilter, $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 = $locale.id;\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 // View vars\n\n var selectedIndex = 0;\n var startDate = controller.$dateValue || new Date();\n var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n var format = $locale.DATETIME_FORMATS[options.timeFormat] || options.timeFormat;\n var formats = /(h+)([:\\.])?(m+)[ ]?(a?)/i.exec(format).slice(1);\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 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: dateFilter(hour, formats[0]), 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: dateFilter(minute, formats[2]), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n }\n\n var rows = [];\n for(i = 0; i < options.length; i++) {\n rows.push([hours[i], minutes[i]]);\n }\n scope.rows = rows;\n scope.showAM = !!formats[3];\n scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n scope.timeSeparator = formats[1];\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 }\n };\n\n $timepicker.$isDisabled = function(date, index) {\n var selectedTime;\n if(index === 0) {\n selectedTime = date.getTime() + viewDate.minute * 6e4;\n } else if(index === 1) {\n selectedTime = date.getTime() + viewDate.hour * 36e5;\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 = dateFilter(newDate, 'h').length;\n var minutes = newDate.getMinutes(), minutesLength = dateFilter(newDate, 'mm').length;\n if (index === 0) {\n newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n }\n else {\n newDate.setMinutes(minutes - (parseInt(options.minuteStep, 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);\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));\n angular.extend(viewDate, {minute: targetDate.getMinutes()});\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 = dateFilter(newDate, 'h').length;\n var minutes = newDate.getMinutes(), minutesLength = dateFilter(newDate, 'mm').length;\n var lateralMove = /(37|39)/.test(evt.keyCode);\n var count = 2 + !!formats[3] * 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 if(selectedIndex === 0) {\n if(evt.keyCode === 38) newDate.setHours(hours - parseInt(options.hourStep, 10));\n else if(evt.keyCode === 40) newDate.setHours(hours + parseInt(options.hourStep, 10));\n selectRange = [0, hoursLength];\n } else if(selectedIndex === 1) {\n if(evt.keyCode === 38) newDate.setMinutes(minutes - parseInt(options.minuteStep, 10));\n else if(evt.keyCode === 40) newDate.setMinutes(minutes + parseInt(options.minuteStep, 10));\n selectRange = [hoursLength + 1, hoursLength + 1 + minutesLength];\n } else if(selectedIndex === 2) {\n if(!lateralMove) $timepicker.switchMeridian();\n selectRange = [hoursLength + 1 + minutesLength + 1, hoursLength + 1 + minutesLength + 3];\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, end) {\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 $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $timepicker.$onKeyDown);\n }\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, $locale, dateFilter, $timepicker, $dateParser) {\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', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 // Initialize parser\n var dateParser = $dateParser({format: options.timeFormat, lang: options.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 // Null values should correctly reset the model value & validity\n if(!viewValue) {\n controller.$setValidity('date', true);\n return;\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;\n } else {\n validateAgainstMinMaxTime(parsedTime);\n }\n if(options.timeType === 'string') {\n return dateFilter(parsedTime, options.modelTimeFormat || options.timeFormat);\n } else if(options.timeType === 'number') {\n return controller.$dateValue.getTime();\n } else if(options.timeType === 'iso') {\n return controller.$dateValue.toISOString();\n } else {\n return new Date(controller.$dateValue);\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 {\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 = date;\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()) ? '' : dateFilter(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"],"sourceRoot":"/source/"}
\ No newline at end of file
+{"version":3,"sources":["timepicker/timepicker.js"],"names":[],"mappings":"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","file":"timepicker.min.js","sourcesContent":["'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 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 modelTimeFormat: null,\n autoclose: false,\n minTime: -Infinity,\n maxTime: +Infinity,\n length: 5,\n hourStep: 1,\n minuteStep: 5,\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) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n\n // View vars\n\n var selectedIndex = 0;\n var startDate = controller.$dateValue || new Date();\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 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 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\n var rows = [];\n for(i = 0; i < options.length; i++) {\n rows.push([hours[i], minutes[i]]);\n }\n scope.rows = rows;\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 }\n };\n\n $timepicker.$isDisabled = function(date, index) {\n var selectedTime;\n if(index === 0) {\n selectedTime = date.getTime() + viewDate.minute * 6e4;\n } else if(index === 1) {\n selectedTime = date.getTime() + viewDate.hour * 36e5;\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 if (index === 0) {\n newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n }\n else {\n newDate.setMinutes(minutes - (parseInt(options.minuteStep, 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);\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));\n angular.extend(viewDate, {minute: targetDate.getMinutes()});\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 lateralMove = /(37|39)/.test(evt.keyCode);\n var count = 2 + 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 if(selectedIndex === 0) {\n if(evt.keyCode === 38) newDate.setHours(hours - parseInt(options.hourStep, 10));\n else if(evt.keyCode === 40) newDate.setHours(hours + 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 if(evt.keyCode === 38) newDate.setMinutes(minutes - parseInt(options.minuteStep, 10));\n else if(evt.keyCode === 40) newDate.setMinutes(minutes + parseInt(options.minuteStep, 10));\n // re-calculate minutes length because we have changes minutes value\n minutesLength = formatDate(newDate, minutesFormat).length;\n selectRange = [hoursLength + 1, hoursLength + 1 + minutesLength];\n } else if(selectedIndex === 2) {\n if(!lateralMove) $timepicker.switchMeridian();\n selectRange = [hoursLength + 1 + minutesLength + 1, hoursLength + 1 + minutesLength + 3];\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, end) {\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', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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) {\n return $dateFormatter.formatDate(date, format, lang);\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 // 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 if(options.timeType === 'string') {\n return formatDate(parsedTime, options.modelTimeFormat || options.timeFormat);\n } else if(options.timeType === 'number') {\n return controller.$dateValue.getTime();\n } else if(options.timeType === 'iso') {\n return controller.$dateValue.toISOString();\n } else {\n return new Date(controller.$dateValue);\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 {\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 = date;\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"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/dist/modules/timepicker.tpl.js b/dist/modules/timepicker.tpl.js
index 1ed27ac27..c2f8045e0 100644
--- a/dist/modules/timepicker.tpl.js
+++ b/dist/modules/timepicker.tpl.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/timepicker.tpl.min.js b/dist/modules/timepicker.tpl.min.js
index e7f2a7db6..60fcb084c 100644
--- a/dist/modules/timepicker.tpl.min.js
+++ b/dist/modules/timepicker.tpl.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/tooltip.js b/dist/modules/tooltip.js
index 342675376..eeea9d6db 100644
--- a/dist/modules/tooltip.js
+++ b/dist/modules/tooltip.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -32,7 +32,7 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
bsEnabled: true
};
- this.$get = ["$window", "$rootScope", "$compile", "$q", "$templateCache", "$http", "$animate", "dimensions", "$$rAF", "$timeout", function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, dimensions, $$rAF, $timeout) {
+ this.$get = ["$window", "$rootScope", "$compile", "$q", "$templateCache", "$http", "$animate", "$sce", "dimensions", "$$rAF", "$timeout", function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {
var trim = String.prototype.trim;
var isTouch = 'createTouch' in $window.document;
@@ -55,7 +55,7 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
// Support scope as string options
if(options.title) {
- $tooltip.$scope.title = options.title;
+ scope.title = $sce.trustAsHtml(options.title);
}
// Provide scope helpers
@@ -134,16 +134,7 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
}
// Options: trigger
- var triggers = options.trigger.split(' ');
- angular.forEach(triggers, function(trigger) {
- if(trigger === 'click') {
- element.on('click', $tooltip.toggle);
- } else if(trigger !== 'manual') {
- element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);
- element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);
- nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);
- }
- });
+ bindTriggerEvents();
// Options: target
if(options.target) {
@@ -162,22 +153,7 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
$tooltip.destroy = function() {
// Unbind events
- var triggers = options.trigger.split(' ');
- for (var i = triggers.length; i--;) {
- var trigger = triggers[i];
- if(trigger === 'click') {
- element.off('click', $tooltip.toggle);
- } else if(trigger !== 'manual') {
- element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);
- element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);
- nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);
- }
- }
-
- if(options.autoClose && $tooltip.$isShown && tipElement !== null) {
- $body.off('click');
- tipElement.off('click');
- }
+ unbindTriggerEvents();
// Remove element
destroyTipElement();
@@ -205,8 +181,19 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
if (!options.bsEnabled) return;
scope.$emit(options.prefixEvent + '.show.before', $tooltip);
- var parent = options.container ? tipContainer : null;
- var after = options.container ? null : element;
+ var parent, after;
+ if (options.container) {
+ parent = tipContainer;
+ if (tipContainer[0].lastChild) {
+ after = angular.element(tipContainer[0].lastChild);
+ } else {
+ after = null;
+ }
+ } else {
+ parent = null;
+ after = element;
+ }
+
// Hide any existing tipElement
if(tipElement) destroyTipElement();
@@ -231,7 +218,7 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
if(promise && promise.then) promise.then(enterAnimateCallback);
$tooltip.$isShown = scope.$isShown = true;
- scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
+ safeDigest(scope);
$$rAF(function () {
$tooltip.$applyPlacement();
@@ -243,27 +230,12 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
if(options.keyboard) {
if(options.trigger !== 'focus') {
$tooltip.focus();
- tipElement.on('keyup', $tooltip.$onKeyUp);
- } else {
- element.on('keyup', $tooltip.$onFocusKeyUp);
}
+ bindKeyboardEvents();
}
if(options.autoClose) {
- // Stop propagation when clicking inside tooltip
- tipElement.on('click', function(event) {
- event.stopPropagation();
- });
-
- // Hide when clicking outside tooltip
- // use $timeout to setup this event, otherwise the
- // click on the element to show the popover will bubble
- // to the body and cause the popover to immediatly hide
- $timeout(function() {
- $body.on('click', function() {
- $tooltip.hide();
- });
- }, 0, false);
+ bindAutoCloseEvents();
}
};
@@ -302,18 +274,16 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
if(promise && promise.then) promise.then(leaveAnimateCallback);
$tooltip.$isShown = scope.$isShown = false;
- scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
+ safeDigest(scope);
// Unbind events
if(options.keyboard && tipElement !== null) {
- tipElement.off('keyup', $tooltip.$onKeyUp);
+ unbindKeyboardEvents();
}
if(options.autoClose && tipElement !== null) {
- $body.off('click');
- tipElement.off('click');
+ unbindAutoCloseEvents();
}
-
};
function leaveAnimateCallback() {
@@ -382,6 +352,77 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
$tooltip.$isShown ? element[0].blur() : element[0].focus();
};
+ // bind/unbind events
+ function bindTriggerEvents() {
+ var triggers = options.trigger.split(' ');
+ angular.forEach(triggers, function(trigger) {
+ if(trigger === 'click') {
+ element.on('click', $tooltip.toggle);
+ } else if(trigger !== 'manual') {
+ element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);
+ element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);
+ nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);
+ }
+ });
+ }
+
+ function unbindTriggerEvents() {
+ var triggers = options.trigger.split(' ');
+ for (var i = triggers.length; i--;) {
+ var trigger = triggers[i];
+ if(trigger === 'click') {
+ element.off('click', $tooltip.toggle);
+ } else if(trigger !== 'manual') {
+ element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);
+ element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);
+ nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);
+ }
+ }
+ }
+
+ function bindKeyboardEvents() {
+ if(options.trigger !== 'focus') {
+ tipElement.on('keyup', $tooltip.$onKeyUp);
+ } else {
+ element.on('keyup', $tooltip.$onFocusKeyUp);
+ }
+ }
+
+ function unbindKeyboardEvents() {
+ if(options.trigger !== 'focus') {
+ tipElement.off('keyup', $tooltip.$onKeyUp);
+ } else {
+ element.off('keyup', $tooltip.$onFocusKeyUp);
+ }
+ }
+
+ var _autoCloseEventsBinded = false;
+ function bindAutoCloseEvents() {
+ // use timeout to hookup the events to prevent
+ // event bubbling from being processed imediately.
+ $timeout(function() {
+ // Stop propagation when clicking inside tooltip
+ tipElement.on('click', stopEventPropagation);
+
+ // Hide when clicking outside tooltip
+ $body.on('click', $tooltip.hide);
+
+ _autoCloseEventsBinded = true;
+ }, 0, false);
+ }
+
+ function unbindAutoCloseEvents() {
+ if (_autoCloseEventsBinded) {
+ tipElement.off('click', stopEventPropagation);
+ $body.off('click', $tooltip.hide);
+ _autoCloseEventsBinded = false;
+ }
+ }
+
+ function stopEventPropagation(event) {
+ event.stopPropagation();
+ }
+
// Private methods
function getPosition() {
@@ -453,12 +494,22 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
// Cancel pending callbacks
clearTimeout(timeout);
- if (tipScope) {
+ if($tooltip.$isShown && tipElement !== null) {
+ if(options.autoClose) {
+ unbindAutoCloseEvents();
+ }
+
+ if(options.keyboard) {
+ unbindKeyboardEvents();
+ }
+ }
+
+ if(tipScope) {
tipScope.$destroy();
tipScope = null;
}
- if (tipElement) {
+ if(tipElement) {
tipElement.remove();
tipElement = $tooltip.$element = null;
}
@@ -470,19 +521,25 @@ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])
// Helper functions
+ function safeDigest(scope) {
+ scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();
+ }
+
function findElement(query, element) {
return angular.element((element || document).querySelectorAll(query));
}
+ var fetchPromises = {};
function fetchTemplate(template) {
- return $q.when($templateCache.get(template) || $http.get(template))
+ if(fetchPromises[template]) return fetchPromises[template];
+ return (fetchPromises[template] = $q.when($templateCache.get(template) || $http.get(template))
.then(function(res) {
if(angular.isObject(res)) {
$templateCache.put(template, res.data);
return res.data;
}
return res;
- });
+ }));
}
return TooltipFactory;
diff --git a/dist/modules/tooltip.min.js b/dist/modules/tooltip.min.js
index bc165259b..2c0d19b7d 100644
--- a/dist/modules/tooltip.min.js
+++ b/dist/modules/tooltip.min.js
@@ -1,9 +1,9 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";angular.module("mgcrea.ngStrap.tooltip",["mgcrea.ngStrap.helpers.dimensions"]).provider("$tooltip",function(){var t=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};this.$get=["$window","$rootScope","$compile","$q","$templateCache","$http","$animate","dimensions","$$rAF","$timeout",function(e,n,o,i,a,l,r,s,c,u){function f(e,i){function a(){E.$emit(k.prefixEvent+".show",v)}function l(){return E.$emit(k.prefixEvent+".hide",v),K&&"focus"===k.trigger?e[0].blur():void b()}function f(){return"body"===k.container?s.offset(k.target[0]||e[0]):s.position(k.target[0]||e[0])}function w(t,e,n,o){var i,a=t.split("-");switch(a[0]){case"right":i={top:e.top+e.height/2-o/2,left:e.left+e.width};break;case"bottom":i={top:e.top+e.height,left:e.left+e.width/2-n/2};break;case"left":i={top:e.top+e.height/2-o/2,left:e.left-n};break;default:i={top:e.top-o,left:e.left+e.width/2-n/2}}if(!a[1])return i;if("top"===a[0]||"bottom"===a[0])switch(a[1]){case"left":i.left=e.left;break;case"right":i.left=e.left+e.width-n}else if("left"===a[0]||"right"===a[0])switch(a[1]){case"top":i.top=e.top-o;break;case"bottom":i.top=e.top+e.height}return i}function b(){clearTimeout(C),A&&(A.$destroy(),A=null),x&&(x.remove(),x=v.$element=null)}var v={},y=e[0].nodeName.toLowerCase(),k=v.$options=angular.extend({},t,i);v.$promise=h(k.template);var E=v.$scope=k.scope&&k.scope.$new()||n.$new();if(k.delay&&angular.isString(k.delay)){var S=k.delay.split(",").map(parseFloat);k.delay=S.length>1?{show:S[0],hide:S[1]}:S[0]}k.title&&(v.$scope.title=k.title),E.$setEnabled=function(t){E.$$postDigest(function(){v.setEnabled(t)})},E.$hide=function(){E.$$postDigest(function(){v.hide()})},E.$show=function(){E.$$postDigest(function(){v.show()})},E.$toggle=function(){E.$$postDigest(function(){v.toggle()})},v.$isShown=E.$isShown=!1;var C,D;k.contentTemplate&&(v.$promise=v.$promise.then(function(t){var e=angular.element(t);return h(k.contentTemplate).then(function(t){var n=p('[ng-bind="content"]',e[0]);return n.length||(n=p('[ng-bind="title"]',e[0])),n.removeAttr("ng-bind").html(t),e[0].outerHTML})}));var T,x,P,F,A;v.$promise.then(function(t){angular.isObject(t)&&(t=t.data),k.html&&(t=t.replace($,'ng-bind-html="')),t=d.apply(t),P=t,T=o(t),v.init()}),v.init=function(){k.delay&&angular.isNumber(k.delay)&&(k.delay={show:k.delay,hide:k.delay}),"self"===k.container?F=e:angular.isElement(k.container)?F=k.container:k.container&&(F=p(k.container));var t=k.trigger.split(" ");angular.forEach(t,function(t){"click"===t?e.on("click",v.toggle):"manual"!==t&&(e.on("hover"===t?"mouseenter":"focus",v.enter),e.on("hover"===t?"mouseleave":"blur",v.leave),"button"===y&&"hover"!==t&&e.on(g?"touchstart":"mousedown",v.$onFocusElementMouseDown))}),k.target&&(k.target=angular.isElement(k.target)?k.target:p(k.target)),k.show&&E.$$postDigest(function(){"focus"===k.trigger?e[0].focus():v.show()})},v.destroy=function(){for(var t=k.trigger.split(" "),n=t.length;n--;){var o=t[n];"click"===o?e.off("click",v.toggle):"manual"!==o&&(e.off("hover"===o?"mouseenter":"focus",v.enter),e.off("hover"===o?"mouseleave":"blur",v.leave),"button"===y&&"hover"!==o&&e.off(g?"touchstart":"mousedown",v.$onFocusElementMouseDown))}k.autoClose&&v.$isShown&&null!==x&&(m.off("click"),x.off("click")),b(),E.$destroy()},v.enter=function(){return clearTimeout(C),D="in",k.delay&&k.delay.show?void(C=setTimeout(function(){"in"===D&&v.show()},k.delay.show)):v.show()},v.show=function(){if(k.bsEnabled){E.$emit(k.prefixEvent+".show.before",v);var t=k.container?F:null,n=k.container?null:e;x&&b(),A=v.$scope.$new(),x=v.$element=T(A,function(){}),x.css({top:"-9999px",left:"-9999px",display:"block",visibility:"hidden"}).addClass(k.placement),k.animation&&x.addClass(k.animation),k.type&&x.addClass(k.prefixClass+"-"+k.type),k.customClass&&x.addClass(k.customClass);var o=r.enter(x,t,n,a);o&&o.then&&o.then(a),v.$isShown=E.$isShown=!0,E.$$phase||E.$root&&E.$root.$$phase||E.$digest(),c(function(){v.$applyPlacement(),x&&x.css({visibility:"visible"})}),k.keyboard&&("focus"!==k.trigger?(v.focus(),x.on("keyup",v.$onKeyUp)):e.on("keyup",v.$onFocusKeyUp)),k.autoClose&&(x.on("click",function(t){t.stopPropagation()}),u(function(){m.on("click",function(){v.hide()})},0,!1))}},v.leave=function(){return clearTimeout(C),D="out",k.delay&&k.delay.hide?void(C=setTimeout(function(){"out"===D&&v.hide()},k.delay.hide)):v.hide()};var K;return v.hide=function(t){if(v.$isShown){E.$emit(k.prefixEvent+".hide.before",v),K=t;var e=r.leave(x,l);e&&e.then&&e.then(l),v.$isShown=E.$isShown=!1,E.$$phase||E.$root&&E.$root.$$phase||E.$digest(),k.keyboard&&null!==x&&x.off("keyup",v.$onKeyUp),k.autoClose&&null!==x&&(m.off("click"),x.off("click"))}},v.toggle=function(){v.$isShown?v.leave():v.enter()},v.focus=function(){x[0].focus()},v.setEnabled=function(t){k.bsEnabled=t},v.$applyPlacement=function(){if(x){var t=f(),e=x.prop("offsetWidth"),n=x.prop("offsetHeight"),o=w(k.placement,t,e,n);o.top+="px",o.left+="px",x.css(o)}},v.$onKeyUp=function(t){27===t.which&&v.$isShown&&(v.hide(),t.stopPropagation())},v.$onFocusKeyUp=function(t){27===t.which&&(e[0].blur(),t.stopPropagation())},v.$onFocusElementMouseDown=function(t){t.preventDefault(),t.stopPropagation(),v.$isShown?e[0].blur():e[0].focus()},v}function p(t,e){return angular.element((e||document).querySelectorAll(t))}function h(t){return i.when(a.get(t)||l.get(t)).then(function(e){return angular.isObject(e)?(a.put(t,e.data),e.data):e})}var d=String.prototype.trim,g="createTouch"in e.document,$=/ng-bind="/gi,m=angular.element(e.document);return f}]}).directive("bsTooltip",["$window","$location","$sce","$tooltip","$$rAF",function(t,e,n,o,i){return{restrict:"EAC",scope:!0,link:function(t,e,a){var l={scope:t};angular.forEach(["template","contentTemplate","placement","container","target","delay","trigger","keyboard","html","animation","type","customClass"],function(t){angular.isDefined(a[t])&&(l[t]=a[t])}),t.hasOwnProperty("title")||(t.title=""),a.$observe("title",function(e){if(angular.isDefined(e)||!t.hasOwnProperty("title")){var o=t.title;t.title=n.trustAsHtml(e),angular.isDefined(o)&&i(function(){r&&r.$applyPlacement()})}}),a.bsTooltip&&t.$watch(a.bsTooltip,function(e,n){angular.isObject(e)?angular.extend(t,e):t.title=e,angular.isDefined(n)&&i(function(){r&&r.$applyPlacement()})},!0),a.bsShow&&t.$watch(a.bsShow,function(t){r&&angular.isDefined(t)&&(angular.isString(t)&&(t=!!t.match(/true|,?(tooltip),?/i)),t===!0?r.show():r.hide())}),a.bsEnabled&&t.$watch(a.bsEnabled,function(t){r&&angular.isDefined(t)&&(angular.isString(t)&&(t=!!t.match(/true|1|,?(tooltip),?/i)),r.setEnabled(t===!1?!1:!0))});var r=o(e,l);t.$on("$destroy",function(){r&&r.destroy(),l=null,r=null})}}}]);
+"use strict";angular.module("mgcrea.ngStrap.tooltip",["mgcrea.ngStrap.helpers.dimensions"]).provider("$tooltip",function(){var t=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};this.$get=["$window","$rootScope","$compile","$q","$templateCache","$http","$animate","$sce","dimensions","$$rAF","$timeout",function(e,n,o,i,a,l,r,s,u,c,f){function p(e,i){function a(){K.$emit(A.prefixEvent+".show",P)}function l(){return K.$emit(A.prefixEvent+".hide",P),W&&"focus"===A.trigger?e[0].blur():void x()}function p(){var t=A.trigger.split(" ");angular.forEach(t,function(t){"click"===t?e.on("click",P.toggle):"manual"!==t&&(e.on("hover"===t?"mouseenter":"focus",P.enter),e.on("hover"===t?"mouseleave":"blur",P.leave),"button"===F&&"hover"!==t&&e.on(m?"touchstart":"mousedown",P.$onFocusElementMouseDown))})}function y(){for(var t=A.trigger.split(" "),n=t.length;n--;){var o=t[n];"click"===o?e.off("click",P.toggle):"manual"!==o&&(e.off("hover"===o?"mouseenter":"focus",P.enter),e.off("hover"===o?"mouseleave":"blur",P.leave),"button"===F&&"hover"!==o&&e.off(m?"touchstart":"mousedown",P.$onFocusElementMouseDown))}}function v(){"focus"!==A.trigger?j.on("keyup",P.$onKeyUp):e.on("keyup",P.$onFocusKeyUp)}function k(){"focus"!==A.trigger?j.off("keyup",P.$onKeyUp):e.off("keyup",P.$onFocusKeyUp)}function E(){f(function(){j.on("click",C),w.on("click",P.hide),z=!0},0,!1)}function S(){z&&(j.off("click",C),w.off("click",P.hide),z=!1)}function C(t){t.stopPropagation()}function D(){return"body"===A.container?u.offset(A.target[0]||e[0]):u.position(A.target[0]||e[0])}function T(t,e,n,o){var i,a=t.split("-");switch(a[0]){case"right":i={top:e.top+e.height/2-o/2,left:e.left+e.width};break;case"bottom":i={top:e.top+e.height,left:e.left+e.width/2-n/2};break;case"left":i={top:e.top+e.height/2-o/2,left:e.left-n};break;default:i={top:e.top-o,left:e.left+e.width/2-n/2}}if(!a[1])return i;if("top"===a[0]||"bottom"===a[0])switch(a[1]){case"left":i.left=e.left;break;case"right":i.left=e.left+e.width-n}else if("left"===a[0]||"right"===a[0])switch(a[1]){case"top":i.top=e.top-o;break;case"bottom":i.top=e.top+e.height}return i}function x(){clearTimeout(O),P.$isShown&&null!==j&&(A.autoClose&&S(),A.keyboard&&k()),N&&(N.$destroy(),N=null),j&&(j.remove(),j=P.$element=null)}var P={},F=e[0].nodeName.toLowerCase(),A=P.$options=angular.extend({},t,i);P.$promise=g(A.template);var K=P.$scope=A.scope&&A.scope.$new()||n.$new();if(A.delay&&angular.isString(A.delay)){var U=A.delay.split(",").map(parseFloat);A.delay=U.length>1?{show:U[0],hide:U[1]}:U[0]}A.title&&(K.title=s.trustAsHtml(A.title)),K.$setEnabled=function(t){K.$$postDigest(function(){P.setEnabled(t)})},K.$hide=function(){K.$$postDigest(function(){P.hide()})},K.$show=function(){K.$$postDigest(function(){P.show()})},K.$toggle=function(){K.$$postDigest(function(){P.toggle()})},P.$isShown=K.$isShown=!1;var O,H;A.contentTemplate&&(P.$promise=P.$promise.then(function(t){var e=angular.element(t);return g(A.contentTemplate).then(function(t){var n=d('[ng-bind="content"]',e[0]);return n.length||(n=d('[ng-bind="title"]',e[0])),n.removeAttr("ng-bind").html(t),e[0].outerHTML})}));var M,j,q,L,N;P.$promise.then(function(t){angular.isObject(t)&&(t=t.data),A.html&&(t=t.replace(b,'ng-bind-html="')),t=$.apply(t),q=t,M=o(t),P.init()}),P.init=function(){A.delay&&angular.isNumber(A.delay)&&(A.delay={show:A.delay,hide:A.delay}),"self"===A.container?L=e:angular.isElement(A.container)?L=A.container:A.container&&(L=d(A.container)),p(),A.target&&(A.target=angular.isElement(A.target)?A.target:d(A.target)),A.show&&K.$$postDigest(function(){"focus"===A.trigger?e[0].focus():P.show()})},P.destroy=function(){y(),x(),K.$destroy()},P.enter=function(){return clearTimeout(O),H="in",A.delay&&A.delay.show?void(O=setTimeout(function(){"in"===H&&P.show()},A.delay.show)):P.show()},P.show=function(){if(A.bsEnabled){K.$emit(A.prefixEvent+".show.before",P);var t,n;A.container?(t=L,n=L[0].lastChild?angular.element(L[0].lastChild):null):(t=null,n=e),j&&x(),N=P.$scope.$new(),j=P.$element=M(N,function(){}),j.css({top:"-9999px",left:"-9999px",display:"block",visibility:"hidden"}).addClass(A.placement),A.animation&&j.addClass(A.animation),A.type&&j.addClass(A.prefixClass+"-"+A.type),A.customClass&&j.addClass(A.customClass);var o=r.enter(j,t,n,a);o&&o.then&&o.then(a),P.$isShown=K.$isShown=!0,h(K),c(function(){P.$applyPlacement(),j&&j.css({visibility:"visible"})}),A.keyboard&&("focus"!==A.trigger&&P.focus(),v()),A.autoClose&&E()}},P.leave=function(){return clearTimeout(O),H="out",A.delay&&A.delay.hide?void(O=setTimeout(function(){"out"===H&&P.hide()},A.delay.hide)):P.hide()};var W;P.hide=function(t){if(P.$isShown){K.$emit(A.prefixEvent+".hide.before",P),W=t;var e=r.leave(j,l);e&&e.then&&e.then(l),P.$isShown=K.$isShown=!1,h(K),A.keyboard&&null!==j&&k(),A.autoClose&&null!==j&&S()}},P.toggle=function(){P.$isShown?P.leave():P.enter()},P.focus=function(){j[0].focus()},P.setEnabled=function(t){A.bsEnabled=t},P.$applyPlacement=function(){if(j){var t=D(),e=j.prop("offsetWidth"),n=j.prop("offsetHeight"),o=T(A.placement,t,e,n);o.top+="px",o.left+="px",j.css(o)}},P.$onKeyUp=function(t){27===t.which&&P.$isShown&&(P.hide(),t.stopPropagation())},P.$onFocusKeyUp=function(t){27===t.which&&(e[0].blur(),t.stopPropagation())},P.$onFocusElementMouseDown=function(t){t.preventDefault(),t.stopPropagation(),P.$isShown?e[0].blur():e[0].focus()};var z=!1;return P}function h(t){t.$$phase||t.$root&&t.$root.$$phase||t.$digest()}function d(t,e){return angular.element((e||document).querySelectorAll(t))}function g(t){return y[t]?y[t]:y[t]=i.when(a.get(t)||l.get(t)).then(function(e){return angular.isObject(e)?(a.put(t,e.data),e.data):e})}var $=String.prototype.trim,m="createTouch"in e.document,b=/ng-bind="/gi,w=angular.element(e.document),y={};return p}]}).directive("bsTooltip",["$window","$location","$sce","$tooltip","$$rAF",function(t,e,n,o,i){return{restrict:"EAC",scope:!0,link:function(t,e,a){var l={scope:t};angular.forEach(["template","contentTemplate","placement","container","target","delay","trigger","keyboard","html","animation","type","customClass"],function(t){angular.isDefined(a[t])&&(l[t]=a[t])}),t.hasOwnProperty("title")||(t.title=""),a.$observe("title",function(e){if(angular.isDefined(e)||!t.hasOwnProperty("title")){var o=t.title;t.title=n.trustAsHtml(e),angular.isDefined(o)&&i(function(){r&&r.$applyPlacement()})}}),a.bsTooltip&&t.$watch(a.bsTooltip,function(e,n){angular.isObject(e)?angular.extend(t,e):t.title=e,angular.isDefined(n)&&i(function(){r&&r.$applyPlacement()})},!0),a.bsShow&&t.$watch(a.bsShow,function(t){r&&angular.isDefined(t)&&(angular.isString(t)&&(t=!!t.match(/true|,?(tooltip),?/i)),t===!0?r.show():r.hide())}),a.bsEnabled&&t.$watch(a.bsEnabled,function(t){r&&angular.isDefined(t)&&(angular.isString(t)&&(t=!!t.match(/true|1|,?(tooltip),?/i)),r.setEnabled(t===!1?!1:!0))});var r=o(e,l);t.$on("$destroy",function(){r&&r.destroy(),l=null,r=null})}}}]);
//# sourceMappingURL=tooltip.min.js.map
\ No newline at end of file
diff --git a/dist/modules/tooltip.min.js.map b/dist/modules/tooltip.min.js.map
old mode 100755
new mode 100644
index 66a0b7b8c..e8ba4d5e0
--- a/dist/modules/tooltip.min.js.map
+++ b/dist/modules/tooltip.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["tooltip/tooltip.js"],"names":[],"mappings":"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","file":"tooltip.min.js","sourcesContent":["'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 };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, 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 // Support scope as string options\n if(options.title) {\n $tooltip.$scope.title = 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 $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 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 // 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 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 if(options.autoClose && $tooltip.$isShown && tipElement !== null) {\n $body.off('click');\n tipElement.off('click');\n }\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) return;\n\n scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n var parent = options.container ? tipContainer : null;\n var after = options.container ? null : element;\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', display: 'block', visibility: 'hidden'}).addClass(options.placement);\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 // 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\n $tooltip.$isShown = scope.$isShown = true;\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n $$rAF(function () {\n $tooltip.$applyPlacement();\n\n // Once placed, make the tooltip visible\n if(tipElement) tipElement.css({visibility: 'visible'});\n }); // var a = bodyEl.offsetWidth + 1; ?\n\n // Bind events\n if(options.keyboard) {\n if(options.trigger !== 'focus') {\n $tooltip.focus();\n tipElement.on('keyup', $tooltip.$onKeyUp);\n } else {\n element.on('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n if(options.autoClose) {\n // Stop propagation when clicking inside tooltip\n tipElement.on('click', function(event) {\n event.stopPropagation();\n });\n\n // Hide when clicking outside tooltip\n // use $timeout to setup this event, otherwise the \n // click on the element to show the popover will bubble \n // to the body and cause the popover to immediatly hide\n $timeout(function() {\n $body.on('click', function() {\n $tooltip.hide();\n });\n }, 0, false);\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 $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 // 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 scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n\n // Unbind events\n if(options.keyboard && tipElement !== null) {\n tipElement.off('keyup', $tooltip.$onKeyUp);\n }\n\n if(options.autoClose && tipElement !== null) {\n $body.off('click');\n tipElement.off('click');\n }\n\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\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 $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 // Protected methods\n\n $tooltip.$applyPlacement = function() {\n if(!tipElement) return;\n\n // Get the position of the tooltip element.\n var elementPosition = getPosition();\n\n // Get the height and width of the tooltip so we can center it.\n var tipWidth = tipElement.prop('offsetWidth'),\n tipHeight = tipElement.prop('offsetHeight');\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(options.placement, elementPosition, tipWidth, tipHeight);\n\n // Now set the calculated positioning.\n tipPosition.top += 'px';\n tipPosition.left += 'px';\n tipElement.css(tipPosition);\n\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 // Private methods\n\n function getPosition() {\n if(options.container === 'body') {\n return dimensions.offset(options.target[0] || element[0]);\n } else {\n return dimensions.position(options.target[0] || element[0]);\n }\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 destroyTipElement() {\n // Cancel pending callbacks\n clearTimeout(timeout);\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 findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n function fetchTemplate(template) {\n return $q.when($templateCache.get(template) || $http.get(template))\n .then(function(res) {\n if(angular.isObject(res)) {\n $templateCache.put(template, res.data);\n return res.data;\n }\n return res;\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', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'type', 'customClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 // 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"],"sourceRoot":"/source/"}
\ No newline at end of file
+{"version":3,"sources":["tooltip/tooltip.js"],"names":[],"mappings":"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","file":"tooltip.min.js","sourcesContent":["'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 };\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 // 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 $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) 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', display: 'block', visibility: 'hidden'}).addClass(options.placement);\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 // 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\n $tooltip.$isShown = scope.$isShown = true;\n safeDigest(scope);\n $$rAF(function () {\n $tooltip.$applyPlacement();\n\n // Once placed, make the tooltip visible\n if(tipElement) tipElement.css({visibility: 'visible'});\n }); // var a = bodyEl.offsetWidth + 1; ?\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 $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 // 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 // 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 $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 // Protected methods\n\n $tooltip.$applyPlacement = function() {\n if(!tipElement) return;\n\n // Get the position of the tooltip element.\n var elementPosition = getPosition();\n\n // Get the height and width of the tooltip so we can center it.\n var tipWidth = tipElement.prop('offsetWidth'),\n tipHeight = tipElement.prop('offsetHeight');\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(options.placement, elementPosition, tipWidth, tipHeight);\n\n // Now set the calculated positioning.\n tipPosition.top += 'px';\n tipPosition.left += 'px';\n tipElement.css(tipPosition);\n\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() {\n if(options.container === 'body') {\n return dimensions.offset(options.target[0] || element[0]);\n } else {\n return dimensions.position(options.target[0] || element[0]);\n }\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 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] = $q.when($templateCache.get(template) || $http.get(template))\n .then(function(res) {\n if(angular.isObject(res)) {\n $templateCache.put(template, res.data);\n return res.data;\n }\n return res;\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', 'target', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'type', 'customClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\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 // 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"],"sourceRoot":"/source/"}
\ No newline at end of file
diff --git a/dist/modules/tooltip.tpl.js b/dist/modules/tooltip.tpl.js
index b0456195d..d061f35cf 100644
--- a/dist/modules/tooltip.tpl.js
+++ b/dist/modules/tooltip.tpl.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/tooltip.tpl.min.js b/dist/modules/tooltip.tpl.min.js
index 19cd05dba..5566678e3 100644
--- a/dist/modules/tooltip.tpl.min.js
+++ b/dist/modules/tooltip.tpl.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/typeahead.js b/dist/modules/typeahead.js
index ee764e73d..26654489d 100644
--- a/dist/modules/typeahead.js
+++ b/dist/modules/typeahead.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
@@ -28,7 +28,7 @@ angular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ng
comparator: ''
};
- this.$get = ["$window", "$rootScope", "$tooltip", function($window, $rootScope, $tooltip) {
+ this.$get = ["$window", "$rootScope", "$tooltip", "$timeout", function($window, $rootScope, $tooltip, $timeout) {
var bodyEl = angular.element($window.document.body);
@@ -141,10 +141,14 @@ angular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ng
var show = $typeahead.show;
$typeahead.show = function() {
show();
- $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);
- if(options.keyboard) {
- element.on('keydown', $typeahead.$onKeyDown);
- }
+ // use timeout to hookup the events to prevent
+ // event bubbling from being processed imediately.
+ $timeout(function() {
+ $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);
+ if(options.keyboard) {
+ element.on('keydown', $typeahead.$onKeyDown);
+ }
+ }, 0, false);
};
var hide = $typeahead.hide;
@@ -245,7 +249,7 @@ angular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ng
if(controller.$isEmpty(controller.$viewValue)) return element.val('');
var index = typeahead.$getIndex(controller.$modelValue);
var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;
- selected = angular.isObject(selected) ? selected.label : selected;
+ selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;
element.val(selected ? selected.toString().replace(/<(?:.|\n)*?>/gm, '').trim() : '');
};
diff --git a/dist/modules/typeahead.min.js b/dist/modules/typeahead.min.js
index 6648446f4..fd5cdb948 100644
--- a/dist/modules/typeahead.min.js
+++ b/dist/modules/typeahead.min.js
@@ -1,9 +1,9 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
*/
-"use strict";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,comparator:""};this.$get=["$window","$rootScope","$tooltip",function(t,n,a){function i(t,n,i){var o={},r=angular.extend({},e,i);o=a(t,r);var l=i.scope,c=o.$scope;c.$resetMatches=function(){c.$matches=[],c.$activeIndex=0},c.$resetMatches(),c.$activate=function(e){c.$$postDigest(function(){o.activate(e)})},c.$select=function(e){c.$$postDigest(function(){o.select(e)})},c.$isVisible=function(){return o.$isVisible()},o.update=function(e){c.$matches=e,c.$activeIndex>=e.length&&(c.$activeIndex=0)},o.activate=function(e){c.$activeIndex=e},o.select=function(e){var t=c.$matches[e].value;n.$setViewValue(t),n.$render(),c.$resetMatches(),l&&l.$digest(),c.$emit(r.prefixEvent+".select",t,e)},o.$isVisible=function(){return r.minLength&&n?c.$matches.length&&angular.isString(n.$viewValue)&&n.$viewValue.length>=r.minLength:!!c.$matches.length},o.$getIndex=function(e){var t=c.$matches.length,n=t;if(t){for(n=t;n--&&c.$matches[n].value!==e;);if(!(0>n))return n}},o.$onMouseDown=function(e){e.preventDefault(),e.stopPropagation()},o.$onKeyDown=function(e){/(38|40|13)/.test(e.keyCode)&&(o.$isVisible()&&(e.preventDefault(),e.stopPropagation()),13===e.keyCode&&c.$matches.length?o.select(c.$activeIndex):38===e.keyCode&&c.$activeIndex>0?c.$activeIndex--:40===e.keyCode&&c.$activeIndex0)return void r.$setViewValue(r.$viewValue.substring(0,r.$viewValue.length-1));e.length>s&&(e=e.slice(0,s));var n=f.$isVisible();n&&f.update(e),(1!==e.length||e[0].value!==t)&&(!n&&f.update(e),r.$render())})}),r.$formatters.push(function(e){var t=d.displayValue(e);return void 0===t?"":t}),r.$render=function(){if(r.$isEmpty(r.$viewValue))return t.val("");var e=f.$getIndex(r.$modelValue),n=angular.isDefined(e)?f.$scope.$matches[e].label:r.$viewValue;n=angular.isObject(n)?n.label:n,t.val(n?n.toString().replace(/<(?:.|\n)*?>/gm,"").trim():"")},e.$on("$destroy",function(){f&&f.destroy(),l=null,f=null})}}}]);
+"use strict";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,comparator:""};this.$get=["$window","$rootScope","$tooltip","$timeout",function(t,n,a,i){function o(t,n,o){var r={},l=angular.extend({},e,o);r=a(t,l);var c=o.scope,s=r.$scope;s.$resetMatches=function(){s.$matches=[],s.$activeIndex=0},s.$resetMatches(),s.$activate=function(e){s.$$postDigest(function(){r.activate(e)})},s.$select=function(e){s.$$postDigest(function(){r.select(e)})},s.$isVisible=function(){return r.$isVisible()},r.update=function(e){s.$matches=e,s.$activeIndex>=e.length&&(s.$activeIndex=0)},r.activate=function(e){s.$activeIndex=e},r.select=function(e){var t=s.$matches[e].value;n.$setViewValue(t),n.$render(),s.$resetMatches(),c&&c.$digest(),s.$emit(l.prefixEvent+".select",t,e)},r.$isVisible=function(){return l.minLength&&n?s.$matches.length&&angular.isString(n.$viewValue)&&n.$viewValue.length>=l.minLength:!!s.$matches.length},r.$getIndex=function(e){var t=s.$matches.length,n=t;if(t){for(n=t;n--&&s.$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()&&(e.preventDefault(),e.stopPropagation()),13===e.keyCode&&s.$matches.length?r.select(s.$activeIndex):38===e.keyCode&&s.$activeIndex>0?s.$activeIndex--:40===e.keyCode&&s.$activeIndex0)return void r.$setViewValue(r.$viewValue.substring(0,r.$viewValue.length-1));e.length>s&&(e=e.slice(0,s));var n=f.$isVisible();n&&f.update(e),(1!==e.length||e[0].value!==t)&&(!n&&f.update(e),r.$render())})}),r.$formatters.push(function(e){var t=d.displayValue(e);return void 0===t?"":t}),r.$render=function(){if(r.$isEmpty(r.$viewValue))return t.val("");var e=f.$getIndex(r.$modelValue),n=angular.isDefined(e)?f.$scope.$matches[e].label:r.$viewValue;n=angular.isObject(n)?d.displayValue(n):n,t.val(n?n.toString().replace(/<(?:.|\n)*?>/gm,"").trim():"")},e.$on("$destroy",function(){f&&f.destroy(),l=null,f=null})}}}]);
//# sourceMappingURL=typeahead.min.js.map
\ No newline at end of file
diff --git a/dist/modules/typeahead.min.js.map b/dist/modules/typeahead.min.js.map
old mode 100755
new mode 100644
index fc418b732..05bb028f8
--- a/dist/modules/typeahead.min.js.map
+++ b/dist/modules/typeahead.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["typeahead/typeahead.js"],"names":[],"mappings":"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","file":"typeahead.min.js","sourcesContent":["'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 comparator: ''\n };\n\n this.$get = function($window, $rootScope, $tooltip) {\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 = 0;\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 = 0;\n }\n };\n\n $typeahead.activate = function(index) {\n scope.$activeIndex = index;\n };\n\n $typeahead.select = function(index) {\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);\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\n if($typeahead.$isVisible()) {\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 $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $typeahead.$onKeyDown);\n }\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 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', 'comparator'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Build proper ngOptions\n var filter = options.filter || defaults.filter;\n var limit = options.limit || defaults.limit;\n var comparator = options.comparator || defaults.comparator;\n\n var ngOptions = attr.ngOptions;\n if(filter) ngOptions += ' | ' + filter + ':$viewValue';\n if (comparator) ngOptions += ':' + comparator;\n if(limit) ngOptions += ' | limitTo:' + limit;\n var parsedOptions = $parseOptions(ngOptions);\n\n // Initialize typeahead\n var typeahead = $typeahead(element, controller, options);\n\n // Watch options on demand\n if(options.watchOptions) {\n // Watch ngOptions values before filtering for changes, drop function calls\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n scope.$watch(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 }, true);\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) ? selected.label : selected;\n element.val(selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '').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/"}
\ No newline at end of file
+{"version":3,"sources":["typeahead/typeahead.js"],"names":[],"mappings":"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","file":"typeahead.min.js","sourcesContent":["'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 comparator: ''\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 = 0;\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 = 0;\n }\n };\n\n $typeahead.activate = function(index) {\n scope.$activeIndex = index;\n };\n\n $typeahead.select = function(index) {\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);\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\n if($typeahead.$isVisible()) {\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 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', 'comparator'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Build proper ngOptions\n var filter = options.filter || defaults.filter;\n var limit = options.limit || defaults.limit;\n var comparator = options.comparator || defaults.comparator;\n\n var ngOptions = attr.ngOptions;\n if(filter) ngOptions += ' | ' + filter + ':$viewValue';\n if (comparator) ngOptions += ':' + comparator;\n if(limit) ngOptions += ' | limitTo:' + limit;\n var parsedOptions = $parseOptions(ngOptions);\n\n // Initialize typeahead\n var typeahead = $typeahead(element, controller, options);\n\n // Watch options on demand\n if(options.watchOptions) {\n // Watch ngOptions values before filtering for changes, drop function calls\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n scope.$watch(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 }, true);\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 element.val(selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '').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/"}
\ No newline at end of file
diff --git a/dist/modules/typeahead.tpl.js b/dist/modules/typeahead.tpl.js
index e0e36d108..47d479e4e 100644
--- a/dist/modules/typeahead.tpl.js
+++ b/dist/modules/typeahead.tpl.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/dist/modules/typeahead.tpl.min.js b/dist/modules/typeahead.tpl.min.js
index 43d82d320..98ea30d43 100644
--- a/dist/modules/typeahead.tpl.min.js
+++ b/dist/modules/typeahead.tpl.min.js
@@ -1,6 +1,6 @@
/**
* angular-strap
- * @version v2.1.3 - 2014-11-06
+ * @version v2.1.4 - 2014-11-26
* @link http://mgcrea.github.io/angular-strap
* @author Olivier Louvignes (olivier@mg-crea.com)
* @license MIT License, http://www.opensource.org/licenses/MIT
diff --git a/docs/index.html b/docs/index.html
index f152a83bd..f2e19b15f 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -33,7 +33,7 @@
-
+
diff --git a/docs/scripts/app.js b/docs/scripts/app.js
index 2dff6e465..836727f44 100644
--- a/docs/scripts/app.js
+++ b/docs/scripts/app.js
@@ -3,12 +3,11 @@
angular.module('mgcrea.ngStrapDocs', [
'mgcrea.ngStrap',
'mgcrea.ngPlunkr',
- // 'ngSanitize',
'ngRoute',
'ngAnimate'
])
-.constant('version', 'v2.1.3')
+.constant('version', 'v2.1.4')
.config(function($plunkrProvider, version) {
diff --git a/package.json b/package.json
index 2c57c02c4..818da834e 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "angular-strap",
"description": "AngularStrap - AngularJS directives for Bootstrap",
- "version": "2.1.3",
+ "version": "2.1.4",
"keywords": [
"angular",
"bootstrap"