diff --git a/ajax/libs/angular-strap/2.0.0-rc.1/angular-strap.js b/ajax/libs/angular-strap/2.0.0-rc.1/angular-strap.js
new file mode 100644
index 000000000..7e5262611
--- /dev/null
+++ b/ajax/libs/angular-strap/2.0.0-rc.1/angular-strap.js
@@ -0,0 +1,3118 @@
+/**
+ * angular-strap
+ * @version v2.0.0-rc.1 - 2014-01-28
+ * @link http://mgcrea.github.io/angular-strap
+ * @author [object Object]
+ * @license MIT License, http://www.opensource.org/licenses/MIT
+ */
+(function (window, document, undefined) {
+ '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'
+ ]);
+ angular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions']).provider('$affix', function () {
+ var defaults = this.defaults = { offsetTop: 'auto' };
+ this.$get = [
+ '$window',
+ 'dimensions',
+ function ($window, dimensions) {
+ var windowEl = angular.element($window);
+ var bodyEl = angular.element($window.document.body);
+ function AffixFactory(element, config) {
+ var $affix = {};
+ var options = angular.extend({}, defaults, config);
+ var reset = 'affix affix-top affix-bottom', initialAffixTop = 0, initialOffsetTop = 0, affixed = null, unpin = null;
+ var parent = element.parent();
+ if (options.offsetParent) {
+ if (options.offsetParent.match(/^\d+$/)) {
+ for (var i = 0; i < options.offsetParent * 1 - 1; i++) {
+ parent = parent.parent();
+ }
+ } else {
+ parent = angular.element(options.offsetParent);
+ }
+ }
+ var offsetTop = 0;
+ if (options.offsetTop) {
+ if (options.offsetTop === 'auto') {
+ options.offsetTop = '+0';
+ }
+ if (options.offsetTop.match(/^[-+]\d+$/)) {
+ initialAffixTop -= options.offsetTop * 1;
+ if (options.offsetParent) {
+ offsetTop = dimensions.offset(parent[0]).top + options.offsetTop * 1;
+ } else {
+ offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + options.offsetTop * 1;
+ }
+ } else {
+ offsetTop = options.offsetTop * 1;
+ }
+ }
+ var offsetBottom = 0;
+ if (options.offsetBottom) {
+ if (options.offsetParent && options.offsetBottom.match(/^[-+]\d+$/)) {
+ offsetBottom = $window.document.body.scrollHeight - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + options.offsetBottom * 1 + 1;
+ } else {
+ offsetBottom = options.offsetBottom * 1;
+ }
+ }
+ $affix.init = function () {
+ initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;
+ windowEl.on('scroll', this.checkPosition);
+ windowEl.on('click', this.checkPositionWithEventLoop);
+ this.checkPosition();
+ this.checkPositionWithEventLoop();
+ };
+ $affix.destroy = function () {
+ windowEl.off('scroll', this.checkPosition);
+ windowEl.off('click', this.checkPositionWithEventLoop);
+ };
+ $affix.checkPositionWithEventLoop = function () {
+ setTimeout(this.checkPosition, 1);
+ };
+ $affix.checkPosition = function () {
+ var scrollTop = $window.pageYOffset;
+ var position = dimensions.offset(element[0]);
+ var elementHeight = dimensions.height(element[0]);
+ var affix = getRequiredAffixClass(unpin, position, elementHeight);
+ if (affixed === affix)
+ return;
+ affixed = affix;
+ element.removeClass(reset).addClass('affix' + (affix !== 'middle' ? '-' + affix : ''));
+ if (affix === 'top') {
+ unpin = null;
+ element.css('position', options.offsetParent ? '' : 'relative');
+ element.css('top', '');
+ } else if (affix === 'bottom') {
+ if (options.offsetUnpin) {
+ unpin = -(options.offsetUnpin * 1);
+ } else {
+ unpin = position.top - scrollTop;
+ }
+ element.css('position', options.offsetParent ? '' : 'relative');
+ element.css('top', options.offsetParent ? '' : bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop + 'px');
+ } else {
+ unpin = null;
+ element.css('position', 'fixed');
+ element.css('top', initialAffixTop + 'px');
+ }
+ };
+ function getRequiredAffixClass(unpin, position, elementHeight) {
+ var scrollTop = $window.pageYOffset;
+ var scrollHeight = $window.document.body.scrollHeight;
+ if (scrollTop <= offsetTop) {
+ return 'top';
+ } else if (unpin !== null && scrollTop + unpin <= position.top) {
+ return 'middle';
+ } else if (offsetBottom !== null && position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom) {
+ return 'bottom';
+ } else {
+ return 'middle';
+ }
+ }
+ $affix.init();
+ return $affix;
+ }
+ return AffixFactory;
+ }
+ ];
+ }).directive('bsAffix', [
+ '$affix',
+ 'dimensions',
+ function ($affix, dimensions) {
+ return {
+ restrict: 'EAC',
+ link: function postLink(scope, element, attr) {
+ var options = {
+ scope: scope,
+ offsetTop: 'auto'
+ };
+ angular.forEach([
+ 'offsetTop',
+ 'offsetBottom',
+ 'offsetParent',
+ 'offsetUnpin'
+ ], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ var affix = $affix(element, options);
+ scope.$on('$destroy', function () {
+ options = null;
+ affix = null;
+ });
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.alert', []).run([
+ '$templateCache',
+ function ($templateCache) {
+ var template = '' + '
' + '' + ' ' + '
';
+ $templateCache.put('$alert', template);
+ }
+ ]).provider('$alert', function () {
+ var defaults = this.defaults = {
+ animation: 'animation-fade',
+ prefixClass: 'alert',
+ placement: null,
+ template: '$alert',
+ container: false,
+ element: null,
+ backdrop: false,
+ keyboard: true,
+ show: true,
+ duration: false
+ };
+ this.$get = [
+ '$modal',
+ '$timeout',
+ function ($modal, $timeout) {
+ function AlertFactory(config) {
+ var $alert = {};
+ var options = angular.extend({}, defaults, config);
+ $alert = $modal(options);
+ if (options.type) {
+ $alert.$scope.type = options.type;
+ }
+ var show = $alert.show;
+ if (options.duration) {
+ $alert.show = function () {
+ show();
+ $timeout(function () {
+ $alert.hide();
+ }, options.duration * 1000);
+ };
+ }
+ return $alert;
+ }
+ return AlertFactory;
+ }
+ ];
+ }).directive('bsAlert', [
+ '$window',
+ '$location',
+ '$sce',
+ '$alert',
+ function ($window, $location, $sce, $alert) {
+ var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;
+ return {
+ restrict: 'EAC',
+ scope: true,
+ link: function postLink(scope, element, attr, transclusion) {
+ var options = {
+ scope: scope,
+ element: element,
+ show: false
+ };
+ angular.forEach([
+ 'template',
+ 'placement',
+ 'keyboard',
+ 'html',
+ 'container',
+ 'animation',
+ 'duration'
+ ], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ angular.forEach([
+ 'title',
+ 'content',
+ 'type'
+ ], function (key) {
+ attr[key] && attr.$observe(key, function (newValue, oldValue) {
+ scope[key] = newValue;
+ });
+ });
+ attr.bsAlert && scope.$watch(attr.bsAlert, function (newValue, oldValue) {
+ if (angular.isObject(newValue)) {
+ angular.extend(scope, newValue);
+ } else {
+ scope.content = newValue;
+ }
+ }, true);
+ var alert = $alert(options);
+ element.on(attr.trigger || 'click', alert.toggle);
+ scope.$on('$destroy', function () {
+ alert.destroy();
+ options = null;
+ alert = null;
+ });
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal']).provider('$aside', function () {
+ var defaults = this.defaults = {
+ animation: 'animation-fadeAndSlideRight',
+ prefixClass: 'aside',
+ placement: 'right',
+ template: 'aside/aside.tpl.html',
+ contentTemplate: false,
+ container: false,
+ element: null,
+ backdrop: true,
+ keyboard: true,
+ html: false,
+ show: true
+ };
+ this.$get = [
+ '$modal',
+ function ($modal) {
+ function AsideFactory(config) {
+ var $aside = {};
+ var options = angular.extend({}, defaults, config);
+ $aside = $modal(options);
+ return $aside;
+ }
+ return AsideFactory;
+ }
+ ];
+ }).directive('bsAside', [
+ '$window',
+ '$location',
+ '$sce',
+ '$aside',
+ function ($window, $location, $sce, $aside) {
+ var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;
+ return {
+ restrict: 'EAC',
+ scope: true,
+ link: function postLink(scope, element, attr, transclusion) {
+ var options = {
+ scope: scope,
+ element: element,
+ show: false
+ };
+ angular.forEach([
+ 'template',
+ 'contentTemplate',
+ 'placement',
+ 'backdrop',
+ 'keyboard',
+ 'html',
+ 'container',
+ 'animation'
+ ], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ angular.forEach([
+ 'title',
+ 'content'
+ ], function (key) {
+ attr[key] && attr.$observe(key, function (newValue, oldValue) {
+ scope[key] = newValue;
+ });
+ });
+ attr.bsAside && scope.$watch(attr.bsAside, function (newValue, oldValue) {
+ if (angular.isObject(newValue)) {
+ angular.extend(scope, newValue);
+ } else {
+ scope.content = newValue;
+ }
+ }, true);
+ var aside = $aside(options);
+ element.on(attr.trigger || 'click', aside.toggle);
+ scope.$on('$destroy', function () {
+ aside.destroy();
+ options = null;
+ aside = null;
+ });
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.button', []).provider('$button', function () {
+ var defaults = this.defaults = {
+ activeClass: 'active',
+ toggleEvent: 'click'
+ };
+ this.$get = function () {
+ return { defaults: defaults };
+ };
+ }).directive('bsCheckboxGroup', function () {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ compile: function postLink(element, attr) {
+ element.attr('data-toggle', 'buttons');
+ element.removeAttr('ng-model');
+ var children = element[0].querySelectorAll('input[type="checkbox"]');
+ angular.forEach(children, function (child) {
+ var childEl = angular.element(child);
+ childEl.attr('bs-checkbox', '');
+ childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));
+ });
+ }
+ };
+ }).directive('bsCheckbox', [
+ '$button',
+ function ($button) {
+ var defaults = $button.defaults;
+ var constantValueRegExp = /^(true|false|\d+)$/;
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function postLink(scope, element, attr, controller) {
+ var options = defaults;
+ var isInput = element[0].nodeName === 'INPUT';
+ var activeElement = isInput ? element.parent() : element;
+ var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;
+ if (constantValueRegExp.test(attr.trueValue)) {
+ trueValue = scope.$eval(attr.trueValue);
+ }
+ var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;
+ if (constantValueRegExp.test(attr.falseValue)) {
+ falseValue = scope.$eval(attr.falseValue);
+ }
+ var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';
+ if (hasExoticValues) {
+ controller.$parsers.push(function (viewValue) {
+ return viewValue ? trueValue : falseValue;
+ });
+ scope.$watch(attr.ngModel, function (newValue, oldValue) {
+ controller.$render();
+ });
+ }
+ controller.$render = function () {
+ var isActive = angular.equals(controller.$modelValue, trueValue);
+ if (isInput) {
+ element[0].checked = isActive;
+ }
+ activeElement.toggleClass(options.activeClass, isActive);
+ };
+ element.bind(options.toggleEvent, function () {
+ scope.$apply(function () {
+ if (!isInput) {
+ controller.$setViewValue(!activeElement.hasClass('active'));
+ }
+ if (!hasExoticValues) {
+ controller.$render();
+ }
+ });
+ });
+ }
+ };
+ }
+ ]).directive('bsRadioGroup', function () {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ compile: function postLink(element, attr) {
+ element.attr('data-toggle', 'buttons');
+ element.removeAttr('ng-model');
+ var children = element[0].querySelectorAll('input[type="radio"]');
+ angular.forEach(children, function (child) {
+ angular.element(child).attr('bs-radio', '');
+ angular.element(child).attr('ng-model', attr.ngModel);
+ });
+ }
+ };
+ }).directive('bsRadio', [
+ '$button',
+ function ($button) {
+ var defaults = $button.defaults;
+ var constantValueRegExp = /^(true|false|\d+)$/;
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function postLink(scope, element, attr, controller) {
+ var options = defaults;
+ var isInput = element[0].nodeName === 'INPUT';
+ var activeElement = isInput ? element.parent() : element;
+ var value = constantValueRegExp.test(attr.value) ? scope.$eval(attr.value) : attr.value;
+ controller.$render = function () {
+ var isActive = angular.equals(controller.$modelValue, value);
+ if (isInput) {
+ element[0].checked = isActive;
+ }
+ activeElement.toggleClass(options.activeClass, isActive);
+ };
+ element.bind(options.toggleEvent, function () {
+ scope.$apply(function () {
+ controller.$setViewValue(value);
+ controller.$render();
+ });
+ });
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.datepicker', [
+ 'mgcrea.ngStrap.helpers.dateParser',
+ 'mgcrea.ngStrap.tooltip'
+ ]).provider('$datepicker', function () {
+ var defaults = this.defaults = {
+ animation: 'animation-fade',
+ prefixClass: 'datepicker',
+ placement: 'bottom-left',
+ template: 'datepicker/datepicker.tpl.html',
+ trigger: 'focus',
+ container: false,
+ keyboard: true,
+ html: false,
+ delay: 0,
+ useNative: false,
+ dateType: 'date',
+ dateFormat: 'shortDate',
+ autoclose: false,
+ minDate: -Infinity,
+ maxDate: +Infinity,
+ startView: 0,
+ minView: 0,
+ weekStart: 0
+ };
+ this.$get = [
+ '$window',
+ '$document',
+ '$rootScope',
+ '$sce',
+ '$locale',
+ 'dateFilter',
+ 'datepickerViews',
+ '$tooltip',
+ function ($window, $document, $rootScope, $sce, $locale, dateFilter, datepickerViews, $tooltip) {
+ var bodyEl = angular.element($window.document.body);
+ var isTouch = 'createTouch' in $window.document;
+ var isAppleTouch = /(iP(a|o)d|iPhone)/g.test($window.navigator.userAgent);
+ if (!defaults.lang)
+ defaults.lang = $locale.id;
+ function DatepickerFactory(element, controller, config) {
+ var $datepicker = $tooltip(element, angular.extend({}, defaults, config));
+ var parentScope = config.scope;
+ var options = $datepicker.$options;
+ var scope = $datepicker.$scope;
+ var pickerViews = datepickerViews($datepicker);
+ $datepicker.$views = pickerViews.views;
+ var viewDate = pickerViews.viewDate;
+ scope.$mode = options.startView;
+ var $picker = $datepicker.$views[scope.$mode];
+ scope.$select = function (date) {
+ $datepicker.select(date);
+ };
+ scope.$selectPane = function (value) {
+ $datepicker.$selectPane(value);
+ };
+ scope.$toggleMode = function () {
+ $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);
+ };
+ $datepicker.update = function (date) {
+ if (!isNaN(date.getTime())) {
+ $datepicker.$date = date;
+ $picker.update.call($picker, date);
+ } else if (!$picker.built) {
+ $datepicker.$build();
+ }
+ };
+ $datepicker.select = function (date, keepMode) {
+ if (!angular.isDate(date))
+ date = new Date(date);
+ controller.$dateValue.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
+ if (!scope.$mode || keepMode) {
+ controller.$setViewValue(controller.$dateValue);
+ controller.$render();
+ if (options.autoclose && !keepMode) {
+ $datepicker.hide(true);
+ }
+ } else {
+ angular.extend(viewDate, {
+ year: date.getFullYear(),
+ month: date.getMonth(),
+ date: date.getDate()
+ });
+ $datepicker.setMode(scope.$mode - 1);
+ $datepicker.$build();
+ }
+ };
+ $datepicker.setMode = function (mode) {
+ scope.$mode = mode;
+ $picker = $datepicker.$views[scope.$mode];
+ $datepicker.$build();
+ };
+ $datepicker.$build = function () {
+ $picker.build.call($picker);
+ };
+ $datepicker.$updateSelected = function () {
+ for (var i = 0, l = scope.rows.length; i < l; i++) {
+ angular.forEach(scope.rows[i], updateSelected);
+ }
+ };
+ $datepicker.$isSelected = function (date) {
+ return $picker.isSelected(date);
+ };
+ $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));
+ angular.extend(viewDate, {
+ year: targetDate.getUTCFullYear(),
+ month: targetDate.getUTCMonth(),
+ date: targetDate.getUTCDate()
+ });
+ $datepicker.$build();
+ };
+ $datepicker.$onMouseDown = function (evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (isTouch) {
+ var targetEl = angular.element(evt.target);
+ if (targetEl[0].nodeName.toLowerCase() !== 'button') {
+ targetEl = targetEl.parent();
+ }
+ targetEl.triggerHandler('click');
+ }
+ };
+ $datepicker.$onKeyDown = function (evt) {
+ if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey)
+ return;
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (evt.keyCode === 13) {
+ if (!scope.$mode) {
+ return $datepicker.hide(true);
+ } else {
+ return scope.$apply(function () {
+ $datepicker.setMode(scope.$mode - 1);
+ });
+ }
+ }
+ $picker.onKeyDown(evt);
+ parentScope.$digest();
+ };
+ function updateSelected(el) {
+ el.selected = $datepicker.$isSelected(el.date);
+ }
+ function focusElement() {
+ element[0].focus();
+ }
+ var _init = $datepicker.init;
+ $datepicker.init = function () {
+ if (isAppleTouch && options.useNative) {
+ element.prop('type', 'date');
+ element.css('-webkit-appearance', 'textfield');
+ return;
+ } else if (isTouch) {
+ element.prop('type', 'text');
+ element.attr('readonly', 'true');
+ element.on('click', focusElement);
+ }
+ if (controller.$dateValue) {
+ $datepicker.$date = controller.$dateValue;
+ $datepicker.$build();
+ }
+ _init();
+ };
+ var _destroy = $datepicker.destroy;
+ $datepicker.destroy = function () {
+ if (isAppleTouch && options.useNative) {
+ element.off('click', focusElement);
+ }
+ _destroy();
+ };
+ var _show = $datepicker.show;
+ $datepicker.show = function () {
+ _show();
+ setTimeout(function () {
+ $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);
+ if (options.keyboard) {
+ element.on('keydown', $datepicker.$onKeyDown);
+ }
+ });
+ };
+ var _hide = $datepicker.hide;
+ $datepicker.hide = function (blur) {
+ $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);
+ if (options.keyboard) {
+ element.off('keydown', $datepicker.$onKeyDown);
+ }
+ _hide(blur);
+ };
+ return $datepicker;
+ }
+ DatepickerFactory.defaults = defaults;
+ return DatepickerFactory;
+ }
+ ];
+ }).directive('bsDatepicker', [
+ '$window',
+ '$parse',
+ '$q',
+ '$locale',
+ 'dateFilter',
+ '$datepicker',
+ '$dateParser',
+ '$timeout',
+ function ($window, $parse, $q, $locale, dateFilter, $datepicker, $dateParser, $timeout) {
+ var isAppleTouch = /(iP(a|o)d|iPhone)/g.test($window.navigator.userAgent);
+ var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;
+ return {
+ restrict: 'EAC',
+ require: 'ngModel',
+ link: function postLink(scope, element, attr, controller) {
+ var options = {
+ scope: scope,
+ controller: controller
+ };
+ angular.forEach([
+ 'placement',
+ 'container',
+ 'delay',
+ 'trigger',
+ 'keyboard',
+ 'html',
+ 'animation',
+ 'template',
+ 'autoclose',
+ 'dateType',
+ 'dateFormat',
+ 'useNative',
+ 'lang'
+ ], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ if (isAppleTouch && options.useNative)
+ options.dateFormat = 'yyyy-MM-dd';
+ var datepicker = $datepicker(element, controller, options);
+ options = datepicker.$options;
+ angular.forEach([
+ 'minDate',
+ 'maxDate'
+ ], function (key) {
+ angular.isDefined(attr[key]) && attr.$observe(key, function (newValue) {
+ if (newValue === 'today') {
+ var today = new Date();
+ datepicker.$options[key] = +new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, key === 'minDate' ? 0 : -1);
+ } else if (angular.isString(newValue) && newValue.match(/^".+"$/)) {
+ datepicker.$options[key] = +new Date(newValue.substr(1, newValue.length - 2));
+ } else {
+ datepicker.$options[key] = +new Date(newValue);
+ }
+ !isNaN(datepicker.$options[key]) && datepicker.$build();
+ });
+ });
+ scope.$watch(attr.ngModel, function (newValue, oldValue) {
+ datepicker.update(controller.$dateValue);
+ }, true);
+ var dateParser = $dateParser({
+ format: options.dateFormat,
+ lang: options.lang
+ });
+ controller.$parsers.unshift(function (viewValue) {
+ var parsedDate = dateParser.parse(viewValue, controller.$dateValue);
+ if (!parsedDate || isNaN(parsedDate.getTime())) {
+ controller.$setValidity('date', false);
+ } else {
+ var isValid = parsedDate.getTime() >= options.minDate && parsedDate.getTime() <= options.maxDate;
+ controller.$setValidity('date', isValid);
+ if (isValid)
+ controller.$dateValue = parsedDate;
+ }
+ controller.$dateValue = parsedDate;
+ if (options.dateType === 'string') {
+ return dateFilter(viewValue, options.dateFormat);
+ } else if (options.dateType === 'number') {
+ return controller.$dateValue.getTime();
+ } else if (options.dateType === 'iso') {
+ return controller.$dateValue.toISOString();
+ } else {
+ return controller.$dateValue;
+ }
+ });
+ controller.$formatters.push(function (modelValue) {
+ var date = angular.isDate(modelValue) ? modelValue : new Date(modelValue);
+ controller.$dateValue = date;
+ return controller.$dateValue;
+ });
+ controller.$render = function () {
+ element.val(isNaN(controller.$dateValue.getTime()) ? '' : dateFilter(controller.$dateValue, options.dateFormat));
+ };
+ scope.$on('$destroy', function () {
+ datepicker.destroy();
+ options = null;
+ datepicker = null;
+ });
+ }
+ };
+ }
+ ]).provider('datepickerViews', function () {
+ var defaults = this.defaults = {
+ dayFormat: 'dd',
+ daySplit: 7
+ };
+ function split(arr, size) {
+ var arrays = [];
+ while (arr.length > 0) {
+ arrays.push(arr.splice(0, size));
+ }
+ return arrays;
+ }
+ this.$get = [
+ '$locale',
+ '$sce',
+ 'dateFilter',
+ function ($locale, $sce, dateFilter) {
+ return function (picker) {
+ var scope = picker.$scope;
+ var options = picker.$options;
+ var weekDaysMin = $locale.DATETIME_FORMATS.SHORTDAY;
+ var weekDaysLabels = weekDaysMin.slice(options.weekStart).concat(weekDaysMin.slice(0, options.weekStart));
+ var dayLabelHtml = $sce.trustAsHtml('' + weekDaysLabels.join(' | ') + ' | ');
+ var startDate = picker.$date || new Date();
+ var viewDate = {
+ year: startDate.getFullYear(),
+ month: startDate.getMonth(),
+ date: startDate.getDate()
+ };
+ var timezoneOffset = startDate.getTimezoneOffset() * 60000;
+ var views = [
+ {
+ format: 'dd',
+ split: 7,
+ height: 250,
+ steps: { month: 1 },
+ update: function (date, force) {
+ if (!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {
+ angular.extend(viewDate, {
+ year: picker.$date.getFullYear(),
+ month: picker.$date.getMonth(),
+ date: picker.$date.getDate()
+ });
+ picker.$build();
+ } else if (date.getDate() !== viewDate.date) {
+ viewDate.date = picker.$date.getDate();
+ picker.$updateSelected();
+ }
+ },
+ build: function () {
+ var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1);
+ var firstDate = new Date(+firstDayOfMonth - (firstDayOfMonth.getUTCDay() + 1 - options.weekStart) * 86400000);
+ var days = [], day;
+ for (var i = 0; i < 35; i++) {
+ day = new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i);
+ days.push({
+ date: day,
+ label: dateFilter(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.labels = dayLabelHtml;
+ scope.rows = split(days, this.split);
+ scope.width = 100 / this.split;
+ scope.height = (this.height - 75) / scope.rows.length;
+ this.built = true;
+ },
+ isSelected: function (date) {
+ return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();
+ },
+ isDisabled: function (date) {
+ return date.getTime() < options.minDate || date.getTime() > options.maxDate;
+ },
+ onKeyDown: function (evt) {
+ var actualTime = picker.$date.getTime();
+ if (evt.keyCode === 37)
+ picker.select(new Date(actualTime - 1 * 86400000), true);
+ else if (evt.keyCode === 38)
+ picker.select(new Date(actualTime - 7 * 86400000), true);
+ else if (evt.keyCode === 39)
+ picker.select(new Date(actualTime + 1 * 86400000), true);
+ else if (evt.keyCode === 40)
+ picker.select(new Date(actualTime + 7 * 86400000), true);
+ }
+ },
+ {
+ name: 'month',
+ format: 'MMM',
+ split: 4,
+ height: 250,
+ steps: { year: 1 },
+ update: function (date, force) {
+ if (!this.built || date.getFullYear() !== viewDate.year) {
+ angular.extend(viewDate, {
+ year: picker.$date.getFullYear(),
+ month: picker.$date.getMonth(),
+ date: picker.$date.getDate()
+ });
+ picker.$build();
+ } else if (date.getMonth() !== viewDate.month) {
+ angular.extend(viewDate, {
+ month: picker.$date.getMonth(),
+ date: picker.$date.getDate()
+ });
+ picker.$updateSelected();
+ }
+ },
+ build: function () {
+ var firstMonth = new Date(viewDate.year, 0, 1);
+ 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)
+ });
+ }
+ scope.title = dateFilter(month, 'yyyy');
+ scope.labels = false;
+ scope.rows = split(months, this.split);
+ scope.width = 100 / this.split;
+ scope.height = (this.height - 50) / scope.rows.length;
+ this.built = true;
+ },
+ isSelected: function (date) {
+ return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();
+ },
+ isDisabled: function (date) {
+ var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);
+ return lastDate < options.minDate || date.getTime() > options.maxDate;
+ },
+ onKeyDown: function (evt) {
+ var actualMonth = picker.$date.getMonth();
+ if (evt.keyCode === 37)
+ picker.select(picker.$date.setMonth(actualMonth - 1), true);
+ else if (evt.keyCode === 38)
+ picker.select(picker.$date.setMonth(actualMonth - 4), true);
+ else if (evt.keyCode === 39)
+ picker.select(picker.$date.setMonth(actualMonth + 1), true);
+ else if (evt.keyCode === 40)
+ picker.select(picker.$date.setMonth(actualMonth + 4), true);
+ }
+ },
+ {
+ name: 'year',
+ format: 'yyyy',
+ split: 4,
+ height: 250,
+ steps: { year: 12 },
+ update: function (date, force) {
+ if (!this.built || force || parseInt(date.getFullYear() / 20, 10) !== parseInt(viewDate.year / 20, 10)) {
+ angular.extend(viewDate, {
+ year: picker.$date.getFullYear(),
+ month: picker.$date.getMonth(),
+ date: picker.$date.getDate()
+ });
+ picker.$build();
+ } else if (date.getFullYear() !== viewDate.year) {
+ angular.extend(viewDate, {
+ year: picker.$date.getFullYear(),
+ month: picker.$date.getMonth(),
+ date: picker.$date.getDate()
+ });
+ picker.$updateSelected();
+ }
+ },
+ build: function () {
+ var firstYear = viewDate.year - viewDate.year % (this.split * 3);
+ 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)
+ });
+ }
+ scope.title = years[0].label + '-' + years[years.length - 1].label;
+ scope.labels = false;
+ scope.rows = split(years, this.split);
+ scope.width = 100 / this.split;
+ scope.height = (this.height - 50) / scope.rows.length;
+ this.built = true;
+ },
+ isSelected: function (date) {
+ return picker.$date && date.getFullYear() === picker.$date.getFullYear();
+ },
+ isDisabled: function (date) {
+ var lastDate = +new Date(date.getFullYear() + 1, 0, 0);
+ return lastDate < options.minDate || date.getTime() > options.maxDate;
+ },
+ onKeyDown: function (evt) {
+ var actualYear = picker.$date.getFullYear();
+ if (evt.keyCode === 37)
+ picker.select(picker.$date.setYear(actualYear - 1), true);
+ else if (evt.keyCode === 38)
+ picker.select(picker.$date.setYear(actualYear - 4), true);
+ else if (evt.keyCode === 39)
+ picker.select(picker.$date.setYear(actualYear + 1), true);
+ else if (evt.keyCode === 40)
+ picker.select(picker.$date.setYear(actualYear + 4), true);
+ }
+ }
+ ];
+ return {
+ views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,
+ viewDate: viewDate
+ };
+ };
+ }
+ ];
+ });
+ angular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip']).provider('$dropdown', function () {
+ var defaults = this.defaults = {
+ animation: 'animation-fade',
+ prefixClass: 'dropdown',
+ placement: 'bottom-left',
+ template: 'dropdown/dropdown.tpl.html',
+ trigger: 'click',
+ container: false,
+ keyboard: true,
+ html: false,
+ delay: 0
+ };
+ this.$get = [
+ '$window',
+ '$tooltip',
+ function ($window, $tooltip) {
+ var bodyEl = angular.element($window.document.body);
+ var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;
+ function DropdownFactory(element, config) {
+ var $dropdown = {};
+ var options = angular.extend({}, defaults, config);
+ $dropdown = $tooltip(element, options);
+ $dropdown.$onKeyDown = function (evt) {
+ if (!/(38|40)/.test(evt.keyCode))
+ return;
+ evt.preventDefault();
+ evt.stopPropagation();
+ var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));
+ if (!items.length)
+ return;
+ var index;
+ angular.forEach(items, function (el, i) {
+ if (matchesSelector && matchesSelector.call(el, ':focus'))
+ index = i;
+ });
+ if (evt.keyCode === 38 && index > 0)
+ index--;
+ else if (evt.keyCode === 40 && index < items.length - 1)
+ index++;
+ else if (angular.isUndefined(index))
+ index = 0;
+ items.eq(index)[0].focus();
+ };
+ var show = $dropdown.show;
+ $dropdown.show = function () {
+ show();
+ setTimeout(function () {
+ options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);
+ bodyEl.on('click', onBodyClick);
+ });
+ };
+ var hide = $dropdown.hide;
+ $dropdown.hide = function () {
+ options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);
+ bodyEl.off('click', onBodyClick);
+ hide();
+ };
+ function onBodyClick(evt) {
+ if (evt.target === element[0])
+ return;
+ return evt.target !== element[0] && $dropdown.hide();
+ }
+ return $dropdown;
+ }
+ return DropdownFactory;
+ }
+ ];
+ }).directive('bsDropdown', [
+ '$window',
+ '$location',
+ '$sce',
+ '$dropdown',
+ function ($window, $location, $sce, $dropdown) {
+ return {
+ restrict: 'EAC',
+ scope: true,
+ link: function postLink(scope, element, attr, transclusion) {
+ var options = { scope: scope };
+ angular.forEach([
+ 'placement',
+ 'container',
+ 'delay',
+ 'trigger',
+ 'keyboard',
+ 'html',
+ 'animation',
+ 'template'
+ ], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ attr.bsDropdown && scope.$watch(attr.bsDropdown, function (newValue, oldValue) {
+ scope.content = newValue;
+ }, true);
+ var dropdown = $dropdown(element, options);
+ scope.$on('$destroy', function () {
+ dropdown.destroy();
+ options = null;
+ dropdown = null;
+ });
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.helpers.dateParser', []).provider('$dateParser', [
+ '$localeProvider',
+ function ($localeProvider) {
+ var proto = Date.prototype;
+ function isNumeric(n) {
+ return !isNaN(parseFloat(n)) && isFinite(n);
+ }
+ var defaults = this.defaults = {
+ format: 'shortDate',
+ strict: false
+ };
+ this.$get = [
+ '$locale',
+ function ($locale) {
+ var DateParserFactory = function (config) {
+ var options = angular.extend({}, defaults, config);
+ var $dateParser = {};
+ var regExpMap = {
+ 'sss': '[0-9]{3}',
+ 'ss': '[0-5][0-9]',
+ 's': options.strict ? '[1-5]?[0-9]' : '[0-5][0-9]',
+ 'mm': '[0-5][0-9]',
+ 'm': options.strict ? '[1-5]?[0-9]' : '[0-5][0-9]',
+ 'HH': '[01][0-9]|2[0-3]',
+ 'H': options.strict ? '[0][1-9]|[1][012]' : '[01][0-9]|2[0-3]',
+ 'hh': '[0][1-9]|[1][012]',
+ 'h': options.strict ? '[1-9]|[1][012]' : '[0]?[1-9]|[1][012]',
+ 'a': 'AM|PM',
+ 'EEEE': $locale.DATETIME_FORMATS.DAY.join('|'),
+ 'EEE': $locale.DATETIME_FORMATS.SHORTDAY.join('|'),
+ 'dd': '[0-2][0-9]{1}|[3][01]{1}',
+ 'd': options.strict ? '[1-2]?[0-9]{1}|[3][01]{1}' : '[0-2][0-9]{1}|[3][01]{1}',
+ 'MMMM': $locale.DATETIME_FORMATS.MONTH.join('|'),
+ 'MMM': $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),
+ 'MM': '[0][1-9]|[1][012]',
+ 'M': options.strict ? '[1-9]|[1][012]' : '[0][1-9]|[1][012]',
+ 'yyyy': '(?:(?:[1]{1}[0-9]{1}[0-9]{1}[0-9]{1})|(?:[2]{1}[0-9]{3}))(?![[0-9]])',
+ 'yy': '(?:(?:[0-9]{1}[0-9]{1}))(?![[0-9]])'
+ };
+ var setFnMap = {
+ 'sss': proto.setMilliseconds,
+ 'ss': proto.setSeconds,
+ 's': proto.setSeconds,
+ 'mm': proto.setMinutes,
+ 'm': proto.setMinutes,
+ 'HH': proto.setHours,
+ 'H': proto.setHours,
+ 'hh': proto.setHours,
+ 'h': proto.setHours,
+ 'dd': proto.setDate,
+ 'd': proto.setDate,
+ 'a': function (value) {
+ var hours = this.getHours();
+ return this.setHours(value.match(/pm/i) ? hours + 12 : hours);
+ },
+ 'MMMM': function (value) {
+ return this.setMonth($locale.DATETIME_FORMATS.MONTH.indexOf(value));
+ },
+ 'MMM': function (value) {
+ return this.setMonth($locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value));
+ },
+ 'MM': function (value) {
+ return this.setMonth(1 * value - 1);
+ },
+ 'M': function (value) {
+ return this.setMonth(1 * value - 1);
+ },
+ 'yyyy': proto.setFullYear,
+ 'yy': function (value) {
+ return this.setFullYear(2000 + 1 * value);
+ },
+ 'y': proto.setFullYear
+ };
+ var regex, setMap;
+ $dateParser.init = function () {
+ $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;
+ regex = regExpForFormat($dateParser.$format);
+ setMap = setMapForFormat($dateParser.$format);
+ };
+ $dateParser.isValid = function (date) {
+ if (angular.isDate(date))
+ return !isNaN(date.getTime());
+ return regex.test(date);
+ };
+ $dateParser.parse = function (value, baseDate) {
+ if (angular.isDate(value))
+ return value;
+ var matches = regex.exec(value);
+ if (!matches)
+ return false;
+ var date = baseDate || new Date(0);
+ for (var i = 0; i < matches.length - 1; i++) {
+ setMap[i] && setMap[i].call(date, matches[i + 1]);
+ }
+ return date;
+ };
+ function setMapForFormat(format) {
+ var keys = Object.keys(setFnMap), i;
+ var map = [], sortedMap = [];
+ var clonedFormat = format;
+ for (i = 0; i < keys.length; i++) {
+ if (format.split(keys[i]).length > 1) {
+ var index = clonedFormat.search(keys[i]);
+ format = format.split(keys[i]).join('');
+ if (setFnMap[keys[i]])
+ map[index] = setFnMap[keys[i]];
+ }
+ }
+ angular.forEach(map, function (v) {
+ sortedMap.push(v);
+ });
+ return sortedMap;
+ }
+ function escapeReservedSymbols(text) {
+ return text.replace(/\//g, '[\\/]').replace('/-/g', '[-]').replace(/\./g, '[.]').replace(/\\s/g, '[\\s]');
+ }
+ function regExpForFormat(format) {
+ var keys = Object.keys(regExpMap), i;
+ var re = format;
+ for (i = 0; i < keys.length; i++) {
+ re = re.split(keys[i]).join('${' + i + '}');
+ }
+ for (i = 0; i < keys.length; i++) {
+ re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');
+ }
+ format = escapeReservedSymbols(format);
+ return new RegExp('^' + re + '$', ['i']);
+ }
+ $dateParser.init();
+ return $dateParser;
+ };
+ return DateParserFactory;
+ }
+ ];
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.helpers.debounce', []).constant('debounce', function (func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+ return function () {
+ context = this;
+ args = arguments;
+ timestamp = new Date();
+ var later = function () {
+ var last = new Date() - timestamp;
+ if (last < wait) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ if (!immediate)
+ result = func.apply(context, args);
+ }
+ };
+ var callNow = immediate && !timeout;
+ if (!timeout) {
+ timeout = setTimeout(later, wait);
+ }
+ if (callNow)
+ result = func.apply(context, args);
+ return result;
+ };
+ }).constant('throttle', function (func, wait, options) {
+ var context, args, result;
+ var timeout = null;
+ var previous = 0;
+ options || (options = {});
+ var later = function () {
+ previous = options.leading === false ? 0 : new Date();
+ timeout = null;
+ result = func.apply(context, args);
+ };
+ return function () {
+ var now = new Date();
+ if (!previous && options.leading === false)
+ previous = now;
+ var remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0) {
+ clearTimeout(timeout);
+ timeout = null;
+ previous = now;
+ result = func.apply(context, args);
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ });
+ angular.module('mgcrea.ngStrap.helpers.dimensions', []).factory('dimensions', [
+ '$document',
+ '$window',
+ function ($document, $window) {
+ var jqLite = angular.element;
+ var fn = {};
+ var nodeName = fn.nodeName = function (element, name) {
+ return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();
+ };
+ fn.css = function (element, prop, extra) {
+ var value;
+ if (element.currentStyle) {
+ value = element.currentStyle[prop];
+ } else if (window.getComputedStyle) {
+ value = window.getComputedStyle(element)[prop];
+ } else {
+ value = element.style[prop];
+ }
+ return extra === true ? parseFloat(value) || 0 : value;
+ };
+ fn.offset = function (element) {
+ var boxRect = element.getBoundingClientRect();
+ var docElement = element.ownerDocument;
+ return {
+ width: element.offsetWidth,
+ height: element.offsetHeight,
+ top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),
+ left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)
+ };
+ };
+ fn.position = function (element) {
+ var offsetParentRect = {
+ top: 0,
+ left: 0
+ }, offsetParentElement, offset;
+ if (fn.css(element, 'position') === 'fixed') {
+ offset = element.getBoundingClientRect();
+ } else {
+ offsetParentElement = offsetParent(element);
+ offset = fn.offset(element);
+ offset = fn.offset(element);
+ if (!nodeName(offsetParentElement, 'html')) {
+ offsetParentRect = fn.offset(offsetParentElement);
+ }
+ offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);
+ offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);
+ }
+ return {
+ width: element.offsetWidth,
+ height: element.offsetHeight,
+ top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),
+ left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)
+ };
+ };
+ var offsetParent = function offsetParentElement(element) {
+ var docElement = element.ownerDocument;
+ var offsetParent = element.offsetParent || docElement;
+ if (nodeName(offsetParent, '#document'))
+ return docElement.documentElement;
+ while (offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent || docElement.documentElement;
+ };
+ fn.height = function (element, outer) {
+ var value = element.offsetHeight;
+ if (outer) {
+ value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);
+ } else {
+ value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);
+ }
+ return value;
+ };
+ fn.width = function (element, outer) {
+ var value = element.offsetWidth;
+ if (outer) {
+ value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);
+ } else {
+ value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);
+ }
+ return value;
+ };
+ return fn;
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.helpers.parseOptions', []).provider('$parseOptions', function () {
+ var defaults = this.defaults = { regexp: /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/ };
+ this.$get = [
+ '$parse',
+ '$q',
+ function ($parse, $q) {
+ function ParseOptionsFactory(attr, config) {
+ var $parseOptions = {};
+ var options = angular.extend({}, defaults, config);
+ $parseOptions.$values = [];
+ var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;
+ $parseOptions.init = function () {
+ $parseOptions.$match = match = attr.match(options.regexp);
+ displayFn = $parse(match[2] || match[1]), valueName = match[4] || match[6], keyName = match[5], groupByFn = $parse(match[3] || ''), valueFn = $parse(match[2] ? match[1] : valueName), valuesFn = $parse(match[7]);
+ };
+ $parseOptions.valuesFn = function (scope, controller) {
+ return $q.when(valuesFn(scope, controller)).then(function (values) {
+ $parseOptions.$values = values ? parseValues(values) : {};
+ return $parseOptions.$values;
+ });
+ };
+ function parseValues(values) {
+ return values.map(function (match) {
+ var locals = {}, label, value;
+ locals[valueName] = match;
+ label = displayFn(locals);
+ value = valueFn(locals);
+ if (angular.isObject(value))
+ value = label;
+ return {
+ label: label,
+ value: value
+ };
+ });
+ }
+ $parseOptions.init();
+ return $parseOptions;
+ }
+ return ParseOptionsFactory;
+ }
+ ];
+ });
+ angular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions']).provider('$modal', function () {
+ var defaults = this.defaults = {
+ animation: 'animation-fade',
+ prefixClass: 'modal',
+ placement: 'top',
+ template: 'modal/modal.tpl.html',
+ contentTemplate: false,
+ container: false,
+ element: null,
+ backdrop: true,
+ keyboard: true,
+ html: false,
+ show: true
+ };
+ this.$get = [
+ '$window',
+ '$rootScope',
+ '$compile',
+ '$q',
+ '$templateCache',
+ '$http',
+ '$animate',
+ '$timeout',
+ 'dimensions',
+ function ($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, dimensions) {
+ var forEach = angular.forEach;
+ var jqLite = angular.element;
+ var trim = String.prototype.trim;
+ var bodyElement = jqLite($window.document.body);
+ var htmlReplaceRegExp = /ng-bind="/gi;
+ var findElement = function (query, element) {
+ return jqLite((element || document).querySelectorAll(query));
+ };
+ function ModalFactory(config) {
+ var $modal = {};
+ var options = angular.extend({}, defaults, config);
+ $modal.$promise = $q.when($templateCache.get(options.template) || $http.get(options.template));
+ var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();
+ if (!options.element && !options.container) {
+ options.container = 'body';
+ }
+ if (!options.scope) {
+ forEach([
+ 'title',
+ 'content'
+ ], function (key) {
+ if (options[key])
+ scope[key] = options[key];
+ });
+ }
+ scope.$hide = function () {
+ scope.$$postDigest(function () {
+ $modal.hide();
+ });
+ };
+ scope.$show = function () {
+ scope.$$postDigest(function () {
+ $modal.show();
+ });
+ };
+ scope.$toggle = function () {
+ scope.$$postDigest(function () {
+ $modal.toggle();
+ });
+ };
+ if (options.contentTemplate) {
+ $modal.$promise = $modal.$promise.then(function (template) {
+ if (angular.isObject(template))
+ template = template.data;
+ var templateEl = angular.element(template);
+ return $q.when($templateCache.get(options.contentTemplate) || $http.get(options.contentTemplate, { cache: $templateCache })).then(function (contentTemplate) {
+ if (angular.isObject(contentTemplate))
+ contentTemplate = contentTemplate.data;
+ var contentEl = findElement('[ng-bind="content"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);
+ if (!config.template)
+ contentEl.next().remove();
+ return templateEl[0].outerHTML;
+ });
+ });
+ }
+ var modalLinker, modalElement;
+ var backdropElement = jqLite('');
+ $modal.$promise.then(function (template) {
+ if (angular.isObject(template))
+ template = template.data;
+ if (options.html)
+ template = template.replace(htmlReplaceRegExp, 'ng-bind-html="');
+ template = trim.apply(template);
+ modalLinker = $compile(template);
+ $modal.init();
+ });
+ $modal.init = function () {
+ if (options.show) {
+ scope.$$postDigest(function () {
+ $modal.show();
+ });
+ }
+ };
+ $modal.destroy = function () {
+ if (modalElement) {
+ modalElement.remove();
+ modalElement = null;
+ }
+ if (backdropElement) {
+ backdropElement.remove();
+ backdropElement = null;
+ }
+ scope.$destroy();
+ };
+ $modal.show = function () {
+ var parent = options.container ? findElement(options.container) : null;
+ var after = options.container ? null : options.element;
+ modalElement = $modal.$element = modalLinker(scope, function (clonedElement, scope) {
+ });
+ modalElement.css({ display: 'block' }).addClass(options.placement);
+ if (options.animation) {
+ if (options.backdrop) {
+ backdropElement.addClass('animation-fade');
+ }
+ modalElement.addClass(options.animation);
+ }
+ if (options.backdrop) {
+ $animate.enter(backdropElement, bodyElement, null, function () {
+ });
+ }
+ $animate.enter(modalElement, parent, after, function () {
+ });
+ scope.$isShown = true;
+ scope.$$phase || scope.$digest();
+ $modal.focus();
+ bodyElement.addClass(options.prefixClass + '-open');
+ if (options.backdrop) {
+ modalElement.on('click', hideOnBackdropClick);
+ backdropElement.on('click', hideOnBackdropClick);
+ }
+ if (options.keyboard) {
+ modalElement.on('keyup', $modal.$onKeyUp);
+ }
+ };
+ $modal.hide = function () {
+ $animate.leave(modalElement, function () {
+ bodyElement.removeClass(options.prefixClass + '-open');
+ });
+ if (options.backdrop) {
+ $animate.leave(backdropElement, function () {
+ });
+ }
+ scope.$$phase || scope.$digest();
+ scope.$isShown = false;
+ if (options.backdrop) {
+ modalElement.off('click', hideOnBackdropClick);
+ backdropElement.off('click', hideOnBackdropClick);
+ }
+ if (options.keyboard) {
+ modalElement.off('keyup', $modal.$onKeyUp);
+ }
+ };
+ $modal.toggle = function () {
+ scope.$isShown ? $modal.hide() : $modal.show();
+ };
+ $modal.focus = function () {
+ modalElement[0].focus();
+ };
+ $modal.$onKeyUp = function (evt) {
+ evt.which === 27 && $modal.hide();
+ };
+ function hideOnBackdropClick(evt) {
+ if (evt.target !== evt.currentTarget)
+ return;
+ options.backdrop === 'static' ? $modal.focus() : $modal.hide();
+ }
+ return $modal;
+ }
+ return ModalFactory;
+ }
+ ];
+ }).directive('bsModal', [
+ '$window',
+ '$location',
+ '$sce',
+ '$modal',
+ function ($window, $location, $sce, $modal) {
+ return {
+ restrict: 'EAC',
+ scope: true,
+ link: function postLink(scope, element, attr, transclusion) {
+ var options = {
+ scope: scope,
+ element: element,
+ show: false
+ };
+ angular.forEach([
+ 'template',
+ 'contentTemplate',
+ 'placement',
+ 'backdrop',
+ 'keyboard',
+ 'html',
+ 'container',
+ 'animation'
+ ], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ angular.forEach([
+ 'title',
+ 'content'
+ ], function (key) {
+ attr[key] && attr.$observe(key, function (newValue, oldValue) {
+ scope[key] = newValue;
+ });
+ });
+ attr.bsModal && scope.$watch(attr.bsModal, function (newValue, oldValue) {
+ if (angular.isObject(newValue)) {
+ angular.extend(scope, newValue);
+ } else {
+ scope.content = newValue;
+ }
+ }, true);
+ var modal = $modal(options);
+ element.on(attr.trigger || 'click', modal.toggle);
+ scope.$on('$destroy', function () {
+ modal.destroy();
+ options = null;
+ modal = null;
+ });
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.navbar', []).provider('$navbar', function () {
+ var defaults = this.defaults = {
+ activeClass: 'active',
+ routeAttr: 'data-match-route'
+ };
+ this.$get = function () {
+ return { defaults: defaults };
+ };
+ }).directive('bsNavbar', [
+ '$window',
+ '$location',
+ '$navbar',
+ function ($window, $location, $navbar) {
+ var defaults = $navbar.defaults;
+ return {
+ restrict: 'A',
+ link: function postLink(scope, element, attr, controller) {
+ var options = defaults;
+ angular.forEach(Object.keys(defaults), function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ scope.$watch(function () {
+ return $location.path();
+ }, function (newValue, oldValue) {
+ var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');
+ angular.forEach(liElements, function (li) {
+ var liElement = angular.element(li);
+ var pattern = liElement.attr(options.routeAttr);
+ var regexp = new RegExp('^' + pattern.replace('/', '\\/') + '$', ['i']);
+ if (regexp.test(newValue)) {
+ liElement.addClass(options.activeClass);
+ } else {
+ liElement.removeClass(options.activeClass);
+ }
+ });
+ });
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip']).provider('$popover', function () {
+ var defaults = this.defaults = {
+ animation: 'animation-fade',
+ placement: 'right',
+ template: 'popover/popover.tpl.html',
+ contentTemplate: false,
+ trigger: 'click',
+ keyboard: true,
+ html: false,
+ title: '',
+ content: '',
+ delay: 0,
+ container: false
+ };
+ this.$get = [
+ '$tooltip',
+ function ($tooltip) {
+ function PopoverFactory(element, config) {
+ var options = angular.extend({}, defaults, config);
+ var $popover = $tooltip(element, options);
+ if (options.content) {
+ $popover.$scope.content = options.content;
+ }
+ return $popover;
+ }
+ return PopoverFactory;
+ }
+ ];
+ }).directive('bsPopover', [
+ '$window',
+ '$location',
+ '$sce',
+ '$popover',
+ function ($window, $location, $sce, $popover) {
+ var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;
+ return {
+ restrict: 'EAC',
+ scope: true,
+ link: function postLink(scope, element, attr) {
+ var options = { scope: scope };
+ angular.forEach([
+ 'template',
+ 'contentTemplate',
+ 'placement',
+ 'container',
+ 'delay',
+ 'trigger',
+ 'keyboard',
+ 'html',
+ 'animation'
+ ], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ angular.forEach([
+ 'title',
+ 'content'
+ ], function (key) {
+ attr[key] && attr.$observe(key, function (newValue, oldValue) {
+ scope[key] = newValue;
+ angular.isDefined(oldValue) && requestAnimationFrame(function () {
+ popover && popover.$applyPlacement();
+ });
+ });
+ });
+ attr.bsPopover && scope.$watch(attr.bsPopover, function (newValue, oldValue) {
+ if (angular.isObject(newValue)) {
+ angular.extend(scope, newValue);
+ } else {
+ scope.content = newValue;
+ }
+ angular.isDefined(oldValue) && requestAnimationFrame(function () {
+ popover && popover.$applyPlacement();
+ });
+ }, true);
+ var popover = $popover(element, options);
+ scope.$on('$destroy', function () {
+ popover.destroy();
+ options = null;
+ popover = null;
+ });
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.scrollspy', [
+ 'mgcrea.ngStrap.helpers.debounce',
+ 'mgcrea.ngStrap.helpers.dimensions'
+ ]).provider('$scrollspy', function () {
+ var spies = this.$$spies = {};
+ var defaults = this.defaults = {
+ debounce: 150,
+ throttle: 100,
+ offset: 100
+ };
+ this.$get = [
+ '$window',
+ '$document',
+ '$rootScope',
+ 'dimensions',
+ 'debounce',
+ 'throttle',
+ function ($window, $document, $rootScope, dimensions, debounce, throttle) {
+ var windowEl = angular.element($window);
+ var docEl = angular.element($document.prop('documentElement'));
+ var bodyEl = angular.element($window.document.body);
+ function nodeName(element, name) {
+ return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();
+ }
+ function ScrollSpyFactory(config) {
+ var options = angular.extend({}, defaults, config);
+ if (!options.element)
+ options.element = bodyEl;
+ var isWindowSpy = nodeName(options.element, 'body');
+ var scrollEl = isWindowSpy ? windowEl : options.element;
+ var scrollId = isWindowSpy ? 'window' : options.id;
+ if (spies[scrollId]) {
+ spies[scrollId].$$count++;
+ return spies[scrollId];
+ }
+ var $scrollspy = {};
+ var trackedElements = $scrollspy.$trackedElements = [];
+ var sortedElements = [];
+ var activeTarget;
+ var debouncedCheckPosition;
+ var throttledCheckPosition;
+ var debouncedCheckOffsets;
+ var viewportHeight;
+ var scrollTop;
+ $scrollspy.init = function () {
+ this.$$count = 1;
+ debouncedCheckPosition = debounce(this.checkPosition, options.debounce);
+ throttledCheckPosition = throttle(this.checkPosition, options.throttle);
+ scrollEl.on('click', this.checkPositionWithEventLoop);
+ windowEl.on('resize', debouncedCheckPosition);
+ scrollEl.on('scroll', throttledCheckPosition);
+ debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);
+ $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);
+ $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);
+ debouncedCheckOffsets();
+ if (scrollId) {
+ spies[scrollId] = $scrollspy;
+ }
+ };
+ $scrollspy.destroy = function () {
+ this.$$count--;
+ if (this.$$count > 0) {
+ return;
+ }
+ scrollEl.off('click', this.checkPositionWithEventLoop);
+ windowEl.off('resize', debouncedCheckPosition);
+ scrollEl.off('scroll', debouncedCheckPosition);
+ $rootScope.$off('$viewContentLoaded', debouncedCheckOffsets);
+ $rootScope.$off('$includeContentLoaded', debouncedCheckOffsets);
+ };
+ $scrollspy.checkPosition = function () {
+ if (!sortedElements.length)
+ return;
+ scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;
+ viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));
+ if (scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {
+ return $scrollspy.$activateElement(sortedElements[0]);
+ }
+ for (var i = sortedElements.length; i--;) {
+ if (angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null)
+ continue;
+ if (activeTarget === sortedElements[i].target)
+ continue;
+ if (scrollTop < sortedElements[i].offsetTop)
+ continue;
+ if (sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop)
+ continue;
+ return $scrollspy.$activateElement(sortedElements[i]);
+ }
+ };
+ $scrollspy.checkPositionWithEventLoop = function () {
+ setTimeout(this.checkPosition, 1);
+ };
+ $scrollspy.$activateElement = function (element) {
+ if (activeTarget) {
+ var activeElement = $scrollspy.$getTrackedElement(activeTarget);
+ if (activeElement) {
+ activeElement.source.removeClass('active');
+ if (nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {
+ activeElement.source.parent().parent().removeClass('active');
+ }
+ }
+ }
+ activeTarget = element.target;
+ element.source.addClass('active');
+ if (nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {
+ element.source.parent().parent().addClass('active');
+ }
+ };
+ $scrollspy.$getTrackedElement = function (target) {
+ return trackedElements.filter(function (obj) {
+ return obj.target === target;
+ })[0];
+ };
+ $scrollspy.checkOffsets = function () {
+ angular.forEach(trackedElements, function (trackedElement) {
+ var targetElement = document.querySelector(trackedElement.target);
+ trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;
+ if (options.offset && trackedElement.offsetTop !== null)
+ trackedElement.offsetTop -= options.offset * 1;
+ });
+ sortedElements = trackedElements.filter(function (el) {
+ return el.offsetTop !== null;
+ }).sort(function (a, b) {
+ return a.offsetTop - b.offsetTop;
+ });
+ debouncedCheckPosition();
+ };
+ $scrollspy.trackElement = function (target, source) {
+ trackedElements.push({
+ target: target,
+ source: source
+ });
+ };
+ $scrollspy.untrackElement = function (target, source) {
+ var toDelete;
+ for (var i = trackedElements.length; i--;) {
+ if (trackedElements[i].target === target && trackedElements[i].source === source) {
+ toDelete = i;
+ break;
+ }
+ }
+ trackedElements = trackedElements.splice(toDelete, 1);
+ };
+ $scrollspy.activate = function (i) {
+ trackedElements[i].addClass('active');
+ };
+ $scrollspy.init();
+ return $scrollspy;
+ }
+ return ScrollSpyFactory;
+ }
+ ];
+ }).directive('bsScrollspy', [
+ '$rootScope',
+ 'debounce',
+ 'dimensions',
+ '$scrollspy',
+ function ($rootScope, debounce, dimensions, $scrollspy) {
+ return {
+ restrict: 'EAC',
+ link: function postLink(scope, element, attr) {
+ var options = { scope: scope };
+ angular.forEach([
+ 'offset',
+ 'target'
+ ], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ var scrollspy = $scrollspy(options);
+ scrollspy.trackElement(options.target, element);
+ scope.$on('$destroy', function () {
+ scrollspy.untrackElement(options.target, element);
+ scrollspy.destroy();
+ options = null;
+ scrollspy = null;
+ });
+ }
+ };
+ }
+ ]).directive('bsScrollspyList', [
+ '$rootScope',
+ 'debounce',
+ 'dimensions',
+ '$scrollspy',
+ function ($rootScope, debounce, dimensions, $scrollspy) {
+ return {
+ restrict: 'A',
+ compile: function postLink(element, attr) {
+ var children = element[0].querySelectorAll('li > a[href]');
+ angular.forEach(children, function (child) {
+ var childEl = angular.element(child);
+ childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));
+ });
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.select', [
+ 'mgcrea.ngStrap.tooltip',
+ 'mgcrea.ngStrap.helpers.parseOptions'
+ ]).provider('$select', function () {
+ var defaults = this.defaults = {
+ animation: 'animation-fade',
+ prefixClass: 'select',
+ placement: 'bottom-left',
+ template: 'select/select.tpl.html',
+ trigger: 'focus',
+ container: false,
+ keyboard: true,
+ html: false,
+ delay: 0,
+ multiple: false,
+ sort: true,
+ caretHtml: ' ',
+ placeholder: 'Choose among the following...'
+ };
+ this.$get = [
+ '$window',
+ '$document',
+ '$rootScope',
+ '$tooltip',
+ function ($window, $document, $rootScope, $tooltip) {
+ var bodyEl = angular.element($window.document.body);
+ var isTouch = 'createTouch' in $window.document;
+ function SelectFactory(element, controller, config) {
+ var $select = {};
+ var options = angular.extend({}, defaults, config);
+ $select = $tooltip(element, options);
+ var parentScope = config.scope;
+ var scope = $select.$scope;
+ scope.$matches = [];
+ scope.$activeIndex = 0;
+ scope.$isMultiple = options.multiple;
+ scope.$activate = function (index) {
+ scope.$$postDigest(function () {
+ $select.activate(index);
+ });
+ };
+ scope.$select = function (index, evt) {
+ scope.$$postDigest(function () {
+ $select.select(index);
+ });
+ };
+ scope.$isVisible = function () {
+ return $select.$isVisible();
+ };
+ scope.$isActive = function (index) {
+ return $select.$isActive(index);
+ };
+ $select.update = function (matches) {
+ scope.$matches = matches;
+ if (controller.$modelValue && matches.length) {
+ if (options.multiple && angular.isArray(controller.$modelValue)) {
+ scope.$activeIndex = controller.$modelValue.map(function (value) {
+ return $select.$getIndex(value);
+ });
+ } else {
+ scope.$activeIndex = $select.$getIndex(controller.$modelValue);
+ }
+ } else if (scope.$activeIndex >= matches.length) {
+ scope.$activeIndex = options.multiple ? [] : 0;
+ }
+ };
+ $select.activate = function (index) {
+ if (options.multiple) {
+ scope.$activeIndex.sort();
+ $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);
+ if (options.sort)
+ scope.$activeIndex.sort();
+ } else {
+ scope.$activeIndex = index;
+ }
+ return scope.$activeIndex;
+ };
+ $select.select = function (index) {
+ var value = scope.$matches[index].value;
+ $select.activate(index);
+ if (options.multiple) {
+ controller.$setViewValue(scope.$activeIndex.map(function (index) {
+ return scope.$matches[index].value;
+ }));
+ } else {
+ controller.$setViewValue(value);
+ }
+ controller.$render();
+ if (parentScope)
+ parentScope.$digest();
+ if (!options.multiple) {
+ if (options.trigger === 'focus')
+ element[0].blur();
+ else if ($select.$isShown)
+ $select.hide();
+ }
+ scope.$emit('$select.select', value, index);
+ };
+ $select.$isVisible = function () {
+ if (!options.minLength || !controller) {
+ return scope.$matches.length;
+ }
+ return scope.$matches.length && controller.$viewValue.length >= options.minLength;
+ };
+ $select.$isActive = function (index) {
+ if (options.multiple) {
+ return scope.$activeIndex.indexOf(index) !== -1;
+ } else {
+ return scope.$activeIndex === index;
+ }
+ };
+ $select.$getIndex = function (value) {
+ var l = scope.$matches.length, i = l;
+ if (!l)
+ return;
+ for (i = l; i--;) {
+ if (scope.$matches[i].value === value)
+ break;
+ }
+ if (i < 0)
+ return;
+ return i;
+ };
+ $select.$onElementMouseDown = function (evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ if ($select.$isShown) {
+ element[0].blur();
+ } else {
+ element[0].focus();
+ }
+ };
+ $select.$onMouseDown = function (evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (isTouch) {
+ var targetEl = angular.element(evt.target);
+ targetEl.triggerHandler('click');
+ }
+ };
+ $select.$onKeyDown = function (evt) {
+ if (!/(38|40|13)/.test(evt.keyCode))
+ return;
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (evt.keyCode === 13) {
+ return $select.select(scope.$activeIndex);
+ }
+ if (evt.keyCode === 38 && scope.$activeIndex > 0)
+ scope.$activeIndex--;
+ else if (evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1)
+ scope.$activeIndex++;
+ else if (angular.isUndefined(scope.$activeIndex))
+ scope.$activeIndex = 0;
+ scope.$digest();
+ };
+ var _init = $select.init;
+ $select.init = function () {
+ _init();
+ element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onElementMouseDown);
+ };
+ var _destroy = $select.destroy;
+ $select.destroy = function () {
+ _destroy();
+ element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onElementMouseDown);
+ };
+ var _show = $select.show;
+ $select.show = function () {
+ _show();
+ if (options.multiple) {
+ $select.$element.addClass('select-multiple');
+ }
+ setTimeout(function () {
+ $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);
+ if (options.keyboard) {
+ element.on('keydown', $select.$onKeyDown);
+ }
+ });
+ };
+ var _hide = $select.hide;
+ $select.hide = function () {
+ $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);
+ if (options.keyboard) {
+ element.off('keydown', $select.$onKeyDown);
+ }
+ _hide();
+ };
+ return $select;
+ }
+ SelectFactory.defaults = defaults;
+ return SelectFactory;
+ }
+ ];
+ }).directive('bsSelect', [
+ '$window',
+ '$parse',
+ '$q',
+ '$select',
+ '$parseOptions',
+ function ($window, $parse, $q, $select, $parseOptions) {
+ var defaults = $select.defaults;
+ return {
+ restrict: 'EAC',
+ require: 'ngModel',
+ link: function postLink(scope, element, attr, controller) {
+ var options = { scope: scope };
+ angular.forEach([
+ 'placement',
+ 'container',
+ 'delay',
+ 'trigger',
+ 'keyboard',
+ 'html',
+ 'animation',
+ 'template',
+ 'placeholder',
+ 'multiple'
+ ], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ var parsedOptions = $parseOptions(attr.ngOptions);
+ var select = $select(element, controller, options);
+ scope.$watch(parsedOptions.$match[7], function (newValue, oldValue) {
+ parsedOptions.valuesFn(scope, controller).then(function (values) {
+ select.update(values);
+ controller.$render();
+ });
+ });
+ controller.$render = function () {
+ var selected, index;
+ if (options.multiple && angular.isArray(controller.$modelValue)) {
+ selected = controller.$modelValue.map(function (value) {
+ index = select.$getIndex(value);
+ return angular.isDefined(index) ? select.$scope.$matches[index].label : false;
+ }).filter(angular.isDefined).join(', ');
+ } else {
+ index = select.$getIndex(controller.$modelValue);
+ selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false;
+ }
+ element.html((selected ? selected : attr.placeholder || defaults.placeholder) + defaults.caretHtml);
+ };
+ scope.$on('$destroy', function () {
+ select.destroy();
+ options = null;
+ select = null;
+ });
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.tab', []).run([
+ '$templateCache',
+ function ($templateCache) {
+ $templateCache.put('$pane', '{{pane.content}}');
+ }
+ ]).provider('$tab', function () {
+ var defaults = this.defaults = {
+ animation: 'animation-fade',
+ template: 'tab/tab.tpl.html'
+ };
+ this.$get = function () {
+ return { defaults: defaults };
+ };
+ }).directive('bsTabs', [
+ '$window',
+ '$animate',
+ '$tab',
+ function ($window, $animate, $tab) {
+ var defaults = $tab.defaults;
+ return {
+ restrict: 'EAC',
+ scope: true,
+ require: '?ngModel',
+ templateUrl: function (element, attr) {
+ return attr.template || defaults.template;
+ },
+ link: function postLink(scope, element, attr, controller) {
+ var options = defaults;
+ angular.forEach(['animation'], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ attr.bsTabs && scope.$watch(attr.bsTabs, function (newValue, oldValue) {
+ scope.panes = newValue;
+ }, true);
+ element.addClass('tabs');
+ if (options.animation) {
+ element.addClass(options.animation);
+ }
+ scope.active = scope.activePane = 0;
+ scope.setActive = function (index, ev) {
+ scope.active = index;
+ if (controller) {
+ controller.$setViewValue(index);
+ }
+ };
+ if (controller) {
+ controller.$render = function () {
+ scope.active = controller.$modelValue * 1;
+ };
+ }
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.timepicker', [
+ 'mgcrea.ngStrap.helpers.dateParser',
+ 'mgcrea.ngStrap.tooltip'
+ ]).provider('$timepicker', function () {
+ var defaults = this.defaults = {
+ animation: 'animation-fade',
+ prefixClass: 'timepicker',
+ placement: 'bottom-left',
+ template: 'timepicker/timepicker.tpl.html',
+ trigger: 'focus',
+ container: false,
+ keyboard: true,
+ html: false,
+ delay: 0,
+ useNative: false,
+ timeType: 'date',
+ timeFormat: 'shortTime',
+ autoclose: false,
+ minTime: -Infinity,
+ maxTime: +Infinity,
+ length: 5,
+ hourStep: 1,
+ minuteStep: 5
+ };
+ this.$get = [
+ '$window',
+ '$document',
+ '$rootScope',
+ '$sce',
+ '$locale',
+ 'dateFilter',
+ '$tooltip',
+ function ($window, $document, $rootScope, $sce, $locale, dateFilter, $tooltip) {
+ var bodyEl = angular.element($window.document.body);
+ var isTouch = 'createTouch' in $window.document;
+ var isAppleTouch = /(iP(a|o)d|iPhone)/g.test($window.navigator.userAgent);
+ if (!defaults.lang)
+ defaults.lang = $locale.id;
+ function timepickerFactory(element, controller, config) {
+ var $timepicker = $tooltip(element, angular.extend({}, defaults, config));
+ var parentScope = config.scope;
+ var options = $timepicker.$options;
+ var scope = $timepicker.$scope;
+ 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);
+ scope.$select = function (date, index) {
+ $timepicker.select(date, index);
+ };
+ scope.$moveIndex = function (value, index) {
+ $timepicker.$moveIndex(value, index);
+ };
+ scope.$switchMeridian = function (date) {
+ $timepicker.switchMeridian(date);
+ };
+ $timepicker.update = function (date) {
+ if (!isNaN(date.getTime())) {
+ $timepicker.$date = date;
+ angular.extend(viewDate, {
+ hour: date.getHours(),
+ minute: date.getMinutes(),
+ second: date.getSeconds(),
+ millisecond: date.getMilliseconds()
+ });
+ $timepicker.$build();
+ } else if (!$timepicker.$isBuilt) {
+ $timepicker.$build();
+ }
+ };
+ $timepicker.select = function (date, index, keep) {
+ if (!angular.isDate(date))
+ date = new Date(date);
+ if (index === 0)
+ controller.$dateValue.setHours(date.getHours());
+ else if (index === 1)
+ controller.$dateValue.setMinutes(date.getMinutes());
+ controller.$setViewValue(controller.$dateValue);
+ controller.$render();
+ if (options.autoclose && !keep) {
+ $timepicker.hide(true);
+ }
+ };
+ $timepicker.switchMeridian = function (date) {
+ var hours = (date || controller.$dateValue).getHours();
+ controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12);
+ controller.$render();
+ };
+ $timepicker.$build = function () {
+ var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10);
+ 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)
+ });
+ }
+ 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[1]),
+ selected: $timepicker.$date && $timepicker.$isSelected(minute, 1),
+ disabled: $timepicker.$isDisabled(minute, 1)
+ });
+ }
+ var rows = [];
+ for (i = 0; i < options.length; i++) {
+ rows.push([
+ hours[i],
+ minutes[i]
+ ]);
+ }
+ scope.rows = rows;
+ scope.showAM = !!formats[2];
+ scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;
+ $timepicker.$isBuilt = true;
+ };
+ $timepicker.$isSelected = function (date, index) {
+ if (!$timepicker.$date)
+ return false;
+ else if (index === 0) {
+ return date.getHours() === $timepicker.$date.getHours();
+ } else if (index === 1) {
+ return date.getMinutes() === $timepicker.$date.getMinutes();
+ }
+ };
+ $timepicker.$isDisabled = function (date, index) {
+ var selectedTime;
+ if (index === 0) {
+ selectedTime = date.getTime() + viewDate.minute * 60000;
+ } else if (index === 1) {
+ selectedTime = date.getTime() + viewDate.hour * 3600000;
+ }
+ return selectedTime < options.minTime || selectedTime > options.maxTime;
+ };
+ $timepicker.$moveIndex = function (value, index) {
+ var targetDate;
+ if (index === 0) {
+ targetDate = new Date(1970, 0, 1, viewDate.hour + value * options.length, viewDate.minute);
+ angular.extend(viewDate, { hour: targetDate.getHours() });
+ } else if (index === 1) {
+ targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + value * options.length * 5);
+ angular.extend(viewDate, { minute: targetDate.getMinutes() });
+ }
+ $timepicker.$build();
+ };
+ $timepicker.$onMouseDown = function (evt) {
+ if (evt.target.nodeName.toLowerCase() !== 'input')
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (isTouch) {
+ var targetEl = angular.element(evt.target);
+ if (targetEl[0].nodeName.toLowerCase() !== 'button') {
+ targetEl = targetEl.parent();
+ }
+ targetEl.triggerHandler('click');
+ }
+ };
+ $timepicker.$onKeyDown = function (evt) {
+ if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey)
+ return;
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (evt.keyCode === 13)
+ return $timepicker.hide(true);
+ 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 lateralMove = /(37|39)/.test(evt.keyCode);
+ var count = 2 + !!formats[2] * 1;
+ if (lateralMove) {
+ if (evt.keyCode === 37)
+ selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1;
+ else if (evt.keyCode === 39)
+ selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0;
+ }
+ if (selectedIndex === 0) {
+ if (lateralMove)
+ return createSelection(0, hoursLength);
+ if (evt.keyCode === 38)
+ newDate.setHours(hours - options.hourStep);
+ else if (evt.keyCode === 40)
+ newDate.setHours(hours + options.hourStep);
+ } else if (selectedIndex === 1) {
+ if (lateralMove)
+ return createSelection(hoursLength + 1, hoursLength + 1 + minutesLength);
+ if (evt.keyCode === 38)
+ newDate.setMinutes(minutes - options.minuteStep);
+ else if (evt.keyCode === 40)
+ newDate.setMinutes(minutes + options.minuteStep);
+ } else if (selectedIndex === 2) {
+ if (lateralMove)
+ return createSelection(hoursLength + 1 + minutesLength + 1, hoursLength + 1 + minutesLength + 3);
+ $timepicker.switchMeridian();
+ }
+ $timepicker.select(newDate, selectedIndex, true);
+ parentScope.$digest();
+ };
+ function createSelection(start, end) {
+ if (element[0].createTextRange) {
+ var selRange = element[0].createTextRange();
+ selRange.collapse(true);
+ selRange.moveStart('character', start);
+ selRange.moveEnd('character', end);
+ selRange.select();
+ } else if (element[0].setSelectionRange) {
+ element[0].setSelectionRange(start, end);
+ } else if (angular.isUndefined(element[0].selectionStart)) {
+ element[0].selectionStart = start;
+ element[0].selectionEnd = end;
+ }
+ }
+ function focusElement() {
+ element[0].focus();
+ }
+ var _init = $timepicker.init;
+ $timepicker.init = function () {
+ if (isTouch) {
+ element.prop('type', 'text');
+ element.attr('readonly', 'true');
+ element.on('click', focusElement);
+ }
+ _init();
+ };
+ var _destroy = $timepicker.destroy;
+ $timepicker.destroy = function () {
+ if (isAppleTouch && options.useNative) {
+ element.off('click', focusElement);
+ }
+ _destroy();
+ };
+ var _show = $timepicker.show;
+ $timepicker.show = function () {
+ _show();
+ setTimeout(function () {
+ $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);
+ if (options.keyboard) {
+ element.on('keydown', $timepicker.$onKeyDown);
+ }
+ });
+ };
+ var _hide = $timepicker.hide;
+ $timepicker.hide = function (blur) {
+ $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);
+ if (options.keyboard) {
+ element.off('keydown', $timepicker.$onKeyDown);
+ }
+ _hide(blur);
+ };
+ return $timepicker;
+ }
+ timepickerFactory.defaults = defaults;
+ return timepickerFactory;
+ }
+ ];
+ }).directive('bsTimepicker', [
+ '$window',
+ '$parse',
+ '$q',
+ '$locale',
+ 'dateFilter',
+ '$timepicker',
+ '$dateParser',
+ '$timeout',
+ function ($window, $parse, $q, $locale, dateFilter, $timepicker, $dateParser, $timeout) {
+ var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;
+ return {
+ restrict: 'EAC',
+ require: 'ngModel',
+ link: function postLink(scope, element, attr, controller) {
+ var options = {
+ scope: scope,
+ controller: controller
+ };
+ angular.forEach([
+ 'placement',
+ 'container',
+ 'delay',
+ 'trigger',
+ 'keyboard',
+ 'html',
+ 'animation',
+ 'template',
+ 'autoclose',
+ 'timeType',
+ 'timeFormat',
+ 'useNative',
+ 'lang'
+ ], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ var timepicker = $timepicker(element, controller, options);
+ options = timepicker.$options;
+ var dateParser = $dateParser({
+ format: options.timeFormat,
+ lang: options.lang
+ });
+ angular.forEach([
+ 'minTime',
+ 'maxTime'
+ ], function (key) {
+ angular.isDefined(attr[key]) && attr.$observe(key, function (newValue) {
+ if (newValue === 'now') {
+ timepicker.$options[key] = new Date().setFullYear(1970, 0, 1);
+ } else if (angular.isString(newValue) && newValue.match(/^".+"$/)) {
+ timepicker.$options[key] = +new Date(newValue.substr(1, newValue.length - 2));
+ } else {
+ timepicker.$options[key] = dateParser.parse(newValue);
+ }
+ !isNaN(timepicker.$options[key]) && timepicker.$build();
+ });
+ });
+ scope.$watch(attr.ngModel, function (newValue, oldValue) {
+ timepicker.update(controller.$dateValue);
+ }, true);
+ controller.$parsers.unshift(function (viewValue) {
+ var parsedTime = dateParser.parse(viewValue, controller.$dateValue);
+ if (!parsedTime || isNaN(parsedTime.getTime())) {
+ controller.$setValidity('date', false);
+ } else {
+ var isValid = parsedTime.getTime() >= options.minTime && parsedTime.getTime() <= options.maxTime;
+ controller.$setValidity('date', isValid);
+ if (isValid)
+ controller.$dateValue = parsedTime;
+ }
+ if (options.timeType === 'string') {
+ return dateFilter(viewValue, options.timeFormat);
+ } else if (options.timeType === 'number') {
+ return controller.$dateValue.getTime();
+ } else if (options.timeType === 'iso') {
+ return controller.$dateValue.toISOString();
+ } else {
+ return controller.$dateValue;
+ }
+ });
+ controller.$formatters.push(function (modelValue) {
+ var date = angular.isDate(modelValue) ? modelValue : new Date(modelValue);
+ if (isNaN(date.getTime()))
+ date = new Date(new Date().setMinutes(0) + 3600000);
+ controller.$dateValue = date;
+ return controller.$dateValue;
+ });
+ controller.$render = function () {
+ element.val(isNaN(controller.$dateValue.getTime()) ? '' : dateFilter(controller.$dateValue, options.timeFormat));
+ };
+ scope.$on('$destroy', function () {
+ timepicker.destroy();
+ options = null;
+ timepicker = null;
+ });
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions']).provider('$tooltip', function () {
+ var defaults = this.defaults = {
+ animation: 'animation-fade',
+ prefixClass: 'tooltip',
+ container: false,
+ placement: 'top',
+ template: 'tooltip/tooltip.tpl.html',
+ contentTemplate: false,
+ trigger: 'hover focus',
+ keyboard: false,
+ html: false,
+ show: false,
+ title: '',
+ type: '',
+ delay: 0
+ };
+ this.$get = [
+ '$window',
+ '$rootScope',
+ '$compile',
+ '$q',
+ '$templateCache',
+ '$http',
+ '$animate',
+ '$timeout',
+ 'dimensions',
+ function ($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, dimensions) {
+ var trim = String.prototype.trim;
+ var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;
+ var htmlReplaceRegExp = /ng-bind="/gi;
+ var findElement = function (query, element) {
+ return angular.element((element || document).querySelectorAll(query));
+ };
+ function TooltipFactory(element, config) {
+ var $tooltip = {};
+ var options = $tooltip.$options = angular.extend({}, defaults, config);
+ $tooltip.$promise = $q.when($templateCache.get(options.template) || $http.get(options.template));
+ var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();
+ if (options.delay && angular.isString(options.delay)) {
+ options.delay = parseFloat(options.delay);
+ }
+ if (options.title) {
+ $tooltip.$scope.title = options.title;
+ }
+ scope.$hide = function () {
+ scope.$$postDigest(function () {
+ $tooltip.hide();
+ });
+ };
+ scope.$show = function () {
+ scope.$$postDigest(function () {
+ $tooltip.show();
+ });
+ };
+ scope.$toggle = function () {
+ scope.$$postDigest(function () {
+ $tooltip.toggle();
+ });
+ };
+ $tooltip.$isShown = false;
+ var timeout, hoverState;
+ if (options.contentTemplate) {
+ $tooltip.$promise = $tooltip.$promise.then(function (template) {
+ if (angular.isObject(template))
+ template = template.data;
+ var templateEl = angular.element(template);
+ return $q.when($templateCache.get(options.contentTemplate) || $http.get(options.contentTemplate, { cache: $templateCache })).then(function (contentTemplate) {
+ if (angular.isObject(contentTemplate))
+ contentTemplate = contentTemplate.data;
+ findElement('[ng-bind="content"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);
+ return templateEl[0].outerHTML;
+ });
+ });
+ }
+ var tipLinker, tipElement, tipTemplate;
+ $tooltip.$promise.then(function (template) {
+ if (angular.isObject(template))
+ template = template.data;
+ if (options.html)
+ template = template.replace(htmlReplaceRegExp, 'ng-bind-html="');
+ template = trim.apply(template);
+ tipTemplate = template;
+ tipLinker = $compile(template);
+ $tooltip.init();
+ });
+ $tooltip.init = function () {
+ if (options.delay && angular.isNumber(options.delay)) {
+ options.delay = {
+ show: options.delay,
+ hide: options.delay
+ };
+ }
+ var triggers = options.trigger.split(' ');
+ for (var i = triggers.length; i--;) {
+ var trigger = triggers[i];
+ 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);
+ }
+ }
+ if (options.show) {
+ scope.$$postDigest(function () {
+ options.trigger === 'focus' ? element[0].focus() : $tooltip.show();
+ });
+ }
+ };
+ $tooltip.destroy = function () {
+ 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);
+ }
+ }
+ if (tipElement) {
+ tipElement.remove();
+ tipElement = null;
+ }
+ scope.$destroy();
+ };
+ $tooltip.enter = function () {
+ clearTimeout(timeout);
+ hoverState = 'in';
+ if (!options.delay || !options.delay.show) {
+ return $tooltip.show();
+ }
+ timeout = setTimeout(function () {
+ if (hoverState === 'in')
+ $tooltip.show();
+ }, options.delay.show);
+ };
+ $tooltip.show = function () {
+ var parent = options.container ? findElement(options.container) : null;
+ var after = options.container ? null : element;
+ tipElement = $tooltip.$element = tipLinker(scope, function (clonedElement, scope) {
+ });
+ tipElement.css({
+ top: '0px',
+ left: '0px',
+ display: 'block'
+ }).addClass(options.placement);
+ if (options.animation)
+ tipElement.addClass(options.animation);
+ if (options.type)
+ tipElement.addClass(options.prefixClass + '-' + options.type);
+ $animate.enter(tipElement, parent, after, function () {
+ });
+ $tooltip.$isShown = true;
+ scope.$$phase || scope.$digest();
+ requestAnimationFrame($tooltip.$applyPlacement);
+ if (options.keyboard) {
+ if (options.trigger !== 'focus') {
+ $tooltip.focus();
+ tipElement.on('keyup', $tooltip.$onKeyUp);
+ } else {
+ element.on('keyup', $tooltip.$onFocusKeyUp);
+ }
+ }
+ };
+ $tooltip.leave = function () {
+ if (!$tooltip.$isShown)
+ return;
+ clearTimeout(timeout);
+ hoverState = 'out';
+ if (!options.delay || !options.delay.hide) {
+ return $tooltip.hide();
+ }
+ timeout = setTimeout(function () {
+ if (hoverState === 'out') {
+ $tooltip.hide();
+ }
+ }, options.delay.hide);
+ };
+ $tooltip.hide = function (blur) {
+ $animate.leave(tipElement, function () {
+ });
+ scope.$$phase || scope.$digest();
+ $tooltip.$isShown = false;
+ if (options.keyboard) {
+ tipElement.off('keyup', $tooltip.$onKeyUp);
+ }
+ if (blur && options.trigger === 'focus') {
+ return element[0].blur();
+ }
+ };
+ $tooltip.toggle = function () {
+ $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter();
+ };
+ $tooltip.focus = function () {
+ tipElement[0].focus();
+ };
+ $tooltip.$applyPlacement = function () {
+ if (!tipElement)
+ return;
+ var elementPosition = getPosition();
+ var tipWidth = tipElement.prop('offsetWidth'), tipHeight = tipElement.prop('offsetHeight');
+ var tipPosition = getCalculatedOffset(options.placement, elementPosition, tipWidth, tipHeight);
+ tipPosition.top += 'px';
+ tipPosition.left += 'px';
+ tipElement.css(tipPosition);
+ };
+ $tooltip.$onKeyUp = function (evt) {
+ evt.which === 27 && $tooltip.hide();
+ };
+ $tooltip.$onFocusKeyUp = function (evt) {
+ evt.which === 27 && element[0].blur();
+ };
+ function getPosition() {
+ if (options.container === 'body') {
+ return dimensions.offset(element[0]);
+ } else {
+ return dimensions.position(element[0]);
+ }
+ }
+ function getCalculatedOffset(placement, position, actualWidth, actualHeight) {
+ var offset;
+ var split = placement.split('-');
+ switch (split[0]) {
+ case 'right':
+ offset = {
+ top: position.top + position.height / 2 - actualHeight / 2,
+ left: position.left + position.width
+ };
+ break;
+ case 'bottom':
+ offset = {
+ top: position.top + position.height,
+ left: position.left + position.width / 2 - actualWidth / 2
+ };
+ break;
+ case 'left':
+ offset = {
+ top: position.top + position.height / 2 - actualHeight / 2,
+ left: position.left - actualWidth
+ };
+ break;
+ default:
+ offset = {
+ top: position.top - actualHeight,
+ left: position.left + position.width / 2 - actualWidth / 2
+ };
+ break;
+ }
+ if (!split[1]) {
+ return offset;
+ }
+ if (split[0] === 'top' || split[0] === 'bottom') {
+ switch (split[1]) {
+ case 'left':
+ offset.left = position.left;
+ break;
+ case 'right':
+ offset.left = position.left + position.width - actualWidth;
+ }
+ } else if (split[0] === 'left' || split[0] === 'right') {
+ switch (split[1]) {
+ case 'top':
+ offset.top = position.top - actualHeight;
+ break;
+ case 'bottom':
+ offset.top = position.top + position.height;
+ }
+ }
+ return offset;
+ }
+ return $tooltip;
+ }
+ return TooltipFactory;
+ }
+ ];
+ }).directive('bsTooltip', [
+ '$window',
+ '$location',
+ '$sce',
+ '$tooltip',
+ function ($window, $location, $sce, $tooltip) {
+ var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;
+ return {
+ restrict: 'EAC',
+ scope: true,
+ link: function postLink(scope, element, attr, transclusion) {
+ var options = { scope: scope };
+ angular.forEach([
+ 'template',
+ 'contentTemplate',
+ 'placement',
+ 'container',
+ 'delay',
+ 'trigger',
+ 'keyboard',
+ 'html',
+ 'animation',
+ 'type'
+ ], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ angular.forEach(['title'], function (key) {
+ attr[key] && attr.$observe(key, function (newValue, oldValue) {
+ scope[key] = newValue;
+ angular.isDefined(oldValue) && requestAnimationFrame(function () {
+ tooltip && tooltip.$applyPlacement();
+ });
+ });
+ });
+ attr.bsTooltip && scope.$watch(attr.bsTooltip, function (newValue, oldValue) {
+ if (angular.isObject(newValue)) {
+ angular.extend(scope, newValue);
+ } else {
+ scope.content = newValue;
+ }
+ angular.isDefined(oldValue) && requestAnimationFrame(function () {
+ tooltip && tooltip.$applyPlacement();
+ });
+ }, true);
+ var tooltip = $tooltip(element, options);
+ scope.$on('$destroy', function () {
+ tooltip.destroy();
+ options = null;
+ tooltip = null;
+ });
+ }
+ };
+ }
+ ]);
+ angular.module('mgcrea.ngStrap.typeahead', [
+ 'mgcrea.ngStrap.tooltip',
+ 'mgcrea.ngStrap.helpers.parseOptions'
+ ]).provider('$typeahead', function () {
+ var defaults = this.defaults = {
+ animation: 'animation-fade',
+ prefixClass: 'typeahead',
+ placement: 'bottom-left',
+ template: 'typeahead/typeahead.tpl.html',
+ trigger: 'focus',
+ container: false,
+ keyboard: true,
+ html: false,
+ delay: 0,
+ minLength: 1,
+ limit: 6
+ };
+ this.$get = [
+ '$window',
+ '$rootScope',
+ '$tooltip',
+ function ($window, $rootScope, $tooltip) {
+ var bodyEl = angular.element($window.document.body);
+ function TypeaheadFactory(element, config) {
+ var $typeahead = {};
+ var options = angular.extend({}, defaults, config);
+ var controller = options.controller;
+ $typeahead = $tooltip(element, options);
+ var parentScope = config.scope;
+ var scope = $typeahead.$scope;
+ scope.$matches = [];
+ scope.$activeIndex = 0;
+ scope.$activate = function (index) {
+ scope.$$postDigest(function () {
+ $typeahead.activate(index);
+ });
+ };
+ scope.$select = function (index, evt) {
+ scope.$$postDigest(function () {
+ $typeahead.select(index);
+ });
+ };
+ scope.$isVisible = function () {
+ return $typeahead.$isVisible();
+ };
+ $typeahead.update = function (matches) {
+ scope.$matches = matches;
+ if (scope.$activeIndex >= matches.length) {
+ scope.$activeIndex = 0;
+ }
+ };
+ $typeahead.activate = function (index) {
+ scope.$activeIndex = index;
+ };
+ $typeahead.select = function (index) {
+ var value = scope.$matches[index].value;
+ if (controller) {
+ controller.$setViewValue(value);
+ controller.$render();
+ if (parentScope)
+ parentScope.$digest();
+ }
+ if (options.trigger === 'focus')
+ element[0].blur();
+ else if ($typeahead.$isShown)
+ $typeahead.hide();
+ scope.$activeIndex = 0;
+ scope.$emit('$typeahead.select', value, index);
+ };
+ $typeahead.$isVisible = function () {
+ if (!options.minLength || !controller) {
+ return !!scope.$matches.length;
+ }
+ return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength;
+ };
+ $typeahead.$onMouseDown = function (evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ };
+ $typeahead.$onKeyDown = function (evt) {
+ if (!/(38|40|13)/.test(evt.keyCode))
+ return;
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (evt.keyCode === 13) {
+ return $typeahead.select(scope.$activeIndex);
+ }
+ if (evt.keyCode === 38 && scope.$activeIndex > 0)
+ scope.$activeIndex--;
+ else if (evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1)
+ scope.$activeIndex++;
+ else if (angular.isUndefined(scope.$activeIndex))
+ scope.$activeIndex = 0;
+ scope.$digest();
+ };
+ var show = $typeahead.show;
+ $typeahead.show = function () {
+ show();
+ setTimeout(function () {
+ $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);
+ if (options.keyboard) {
+ element.on('keydown', $typeahead.$onKeyDown);
+ }
+ });
+ };
+ var hide = $typeahead.hide;
+ $typeahead.hide = function () {
+ $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);
+ if (options.keyboard) {
+ element.off('keydown', $typeahead.$onKeyDown);
+ }
+ hide();
+ };
+ return $typeahead;
+ }
+ TypeaheadFactory.defaults = defaults;
+ return TypeaheadFactory;
+ }
+ ];
+ }).directive('bsTypeahead', [
+ '$window',
+ '$parse',
+ '$q',
+ '$typeahead',
+ '$parseOptions',
+ function ($window, $parse, $q, $typeahead, $parseOptions) {
+ var defaults = $typeahead.defaults;
+ return {
+ restrict: 'EAC',
+ require: 'ngModel',
+ link: function postLink(scope, element, attr, controller) {
+ var options = {
+ scope: scope,
+ controller: controller
+ };
+ angular.forEach([
+ 'placement',
+ 'container',
+ 'delay',
+ 'trigger',
+ 'keyboard',
+ 'html',
+ 'animation',
+ 'template',
+ 'limit',
+ 'minLength'
+ ], function (key) {
+ if (angular.isDefined(attr[key]))
+ options[key] = attr[key];
+ });
+ var limit = options.limit || defaults.limit;
+ var parsedOptions = $parseOptions(attr.ngOptions + ' | filter:$viewValue |\xa0limitTo:' + limit);
+ var typeahead = $typeahead(element, options);
+ scope.$watch(attr.ngModel, function (newValue, oldValue) {
+ parsedOptions.valuesFn(scope, controller).then(function (values) {
+ if (values.length > limit)
+ values = values.slice(0, limit);
+ typeahead.update(values);
+ });
+ });
+ scope.$on('$destroy', function () {
+ typeahead.destroy();
+ options = null;
+ typeahead = null;
+ });
+ }
+ };
+ }
+ ]);
+}(window, document));
\ No newline at end of file
diff --git a/ajax/libs/angular-strap/2.0.0-rc.1/angular-strap.min.js b/ajax/libs/angular-strap/2.0.0-rc.1/angular-strap.min.js
new file mode 100644
index 000000000..7a7c27643
--- /dev/null
+++ b/ajax/libs/angular-strap/2.0.0-rc.1/angular-strap.min.js
@@ -0,0 +1,10 @@
+/**
+ * angular-strap
+ * @version v2.0.0-rc.1 - 2014-01-28
+ * @link http://mgcrea.github.io/angular-strap
+ * @author [object Object]
+ * @license MIT License, http://www.opensource.org/licenses/MIT
+ */
+!function(a,b){"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"]),angular.module("mgcrea.ngStrap.affix",["mgcrea.ngStrap.helpers.dimensions"]).provider("$affix",function(){var a=this.defaults={offsetTop:"auto"};this.$get=["$window","dimensions",function(b,c){function d(d,g){function h(a,c,d){var e=b.pageYOffset,f=b.document.body.scrollHeight;return r>=e?"top":null!==a&&e+a<=c.top?"middle":null!==s&&c.top+d+l>=f-s?"bottom":"middle"}var i={},j=angular.extend({},a,g),k="affix affix-top affix-bottom",l=0,m=0,n=null,o=null,p=d.parent();if(j.offsetParent)if(j.offsetParent.match(/^\d+$/))for(var q=0;q<1*j.offsetParent-1;q++)p=p.parent();else p=angular.element(j.offsetParent);var r=0;j.offsetTop&&("auto"===j.offsetTop&&(j.offsetTop="+0"),j.offsetTop.match(/^[-+]\d+$/)?(l-=1*j.offsetTop,r=j.offsetParent?c.offset(p[0]).top+1*j.offsetTop:c.offset(d[0]).top-c.css(d[0],"marginTop",!0)+1*j.offsetTop):r=1*j.offsetTop);var s=0;return j.offsetBottom&&(s=j.offsetParent&&j.offsetBottom.match(/^[-+]\d+$/)?b.document.body.scrollHeight-(c.offset(p[0]).top+c.height(p[0]))+1*j.offsetBottom+1:1*j.offsetBottom),i.init=function(){m=c.offset(d[0]).top+l,e.on("scroll",this.checkPosition),e.on("click",this.checkPositionWithEventLoop),this.checkPosition(),this.checkPositionWithEventLoop()},i.destroy=function(){e.off("scroll",this.checkPosition),e.off("click",this.checkPositionWithEventLoop)},i.checkPositionWithEventLoop=function(){setTimeout(this.checkPosition,1)},i.checkPosition=function(){var a=b.pageYOffset,e=c.offset(d[0]),g=c.height(d[0]),i=h(o,e,g);n!==i&&(n=i,d.removeClass(k).addClass("affix"+("middle"!==i?"-"+i:"")),"top"===i?(o=null,d.css("position",j.offsetParent?"":"relative"),d.css("top","")):"bottom"===i?(o=j.offsetUnpin?-(1*j.offsetUnpin):e.top-a,d.css("position",j.offsetParent?"":"relative"),d.css("top",j.offsetParent?"":f[0].offsetHeight-s-g-m+"px")):(o=null,d.css("position","fixed"),d.css("top",l+"px")))},i.init(),i}var e=angular.element(b),f=angular.element(b.document.body);return d}]}).directive("bsAffix",["$affix","dimensions",function(a){return{restrict:"EAC",link:function(b,c,d){var e={scope:b,offsetTop:"auto"};angular.forEach(["offsetTop","offsetBottom","offsetParent","offsetUnpin"],function(a){angular.isDefined(d[a])&&(e[a]=d[a])});var f=a(c,e);b.$on("$destroy",function(){e=null,f=null})}}}]),angular.module("mgcrea.ngStrap.alert",[]).run(["$templateCache",function(a){var b='
';a.put("$alert",b)}]).provider("$alert",function(){var a=this.defaults={animation:"animation-fade",prefixClass:"alert",placement:null,template:"$alert",container:!1,element:null,backdrop:!1,keyboard:!0,show:!0,duration:!1};this.$get=["$modal","$timeout",function(b,c){function d(d){var e={},f=angular.extend({},a,d);e=b(f),f.type&&(e.$scope.type=f.type);var g=e.show;return f.duration&&(e.show=function(){g(),c(function(){e.hide()},1e3*f.duration)}),e}return d}]}).directive("bsAlert",["$window","$location","$sce","$alert",function(a,b,c,d){a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",scope:!0,link:function(a,b,c){var e={scope:a,element:b,show:!1};angular.forEach(["template","placement","keyboard","html","container","animation","duration"],function(a){angular.isDefined(c[a])&&(e[a]=c[a])}),angular.forEach(["title","content","type"],function(b){c[b]&&c.$observe(b,function(c){a[b]=c})}),c.bsAlert&&a.$watch(c.bsAlert,function(b){angular.isObject(b)?angular.extend(a,b):a.content=b},!0);var f=d(e);b.on(c.trigger||"click",f.toggle),a.$on("$destroy",function(){f.destroy(),e=null,f=null})}}}]),angular.module("mgcrea.ngStrap.aside",["mgcrea.ngStrap.modal"]).provider("$aside",function(){var a=this.defaults={animation:"animation-fadeAndSlideRight",prefixClass:"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(b){function c(c){var d={},e=angular.extend({},a,c);return d=b(e)}return c}]}).directive("bsAside",["$window","$location","$sce","$aside",function(a,b,c,d){a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",scope:!0,link:function(a,b,c){var e={scope:a,element:b,show:!1};angular.forEach(["template","contentTemplate","placement","backdrop","keyboard","html","container","animation"],function(a){angular.isDefined(c[a])&&(e[a]=c[a])}),angular.forEach(["title","content"],function(b){c[b]&&c.$observe(b,function(c){a[b]=c})}),c.bsAside&&a.$watch(c.bsAside,function(b){angular.isObject(b)?angular.extend(a,b):a.content=b},!0);var f=d(e);b.on(c.trigger||"click",f.toggle),a.$on("$destroy",function(){f.destroy(),e=null,f=null})}}}]),angular.module("mgcrea.ngStrap.button",[]).provider("$button",function(){var a=this.defaults={activeClass:"active",toggleEvent:"click"};this.$get=function(){return{defaults:a}}}).directive("bsCheckboxGroup",function(){return{restrict:"A",require:"ngModel",compile:function(a,b){a.attr("data-toggle","buttons"),a.removeAttr("ng-model");var c=a[0].querySelectorAll('input[type="checkbox"]');angular.forEach(c,function(a){var c=angular.element(a);c.attr("bs-checkbox",""),c.attr("ng-model",b.ngModel+"."+c.attr("value"))})}}}).directive("bsCheckbox",["$button",function(a){var b=a.defaults,c=/^(true|false|\d+)$/;return{restrict:"A",require:"ngModel",link:function(a,d,e,f){var g=b,h="INPUT"===d[0].nodeName,i=h?d.parent():d,j=angular.isDefined(e.trueValue)?e.trueValue:!0;c.test(e.trueValue)&&(j=a.$eval(e.trueValue));var k=angular.isDefined(e.falseValue)?e.falseValue:!1;c.test(e.falseValue)&&(k=a.$eval(e.falseValue));var l="boolean"!=typeof j||"boolean"!=typeof k;l&&(f.$parsers.push(function(a){return a?j:k}),a.$watch(e.ngModel,function(){f.$render()})),f.$render=function(){var a=angular.equals(f.$modelValue,j);h&&(d[0].checked=a),i.toggleClass(g.activeClass,a)},d.bind(g.toggleEvent,function(){a.$apply(function(){h||f.$setViewValue(!i.hasClass("active")),l||f.$render()})})}}}]).directive("bsRadioGroup",function(){return{restrict:"A",require:"ngModel",compile:function(a,b){a.attr("data-toggle","buttons"),a.removeAttr("ng-model");var c=a[0].querySelectorAll('input[type="radio"]');angular.forEach(c,function(a){angular.element(a).attr("bs-radio",""),angular.element(a).attr("ng-model",b.ngModel)})}}}).directive("bsRadio",["$button",function(a){var b=a.defaults,c=/^(true|false|\d+)$/;return{restrict:"A",require:"ngModel",link:function(a,d,e,f){var g=b,h="INPUT"===d[0].nodeName,i=h?d.parent():d,j=c.test(e.value)?a.$eval(e.value):e.value;f.$render=function(){var a=angular.equals(f.$modelValue,j);h&&(d[0].checked=a),i.toggleClass(g.activeClass,a)},d.bind(g.toggleEvent,function(){a.$apply(function(){f.$setViewValue(j),f.$render()})})}}}]),angular.module("mgcrea.ngStrap.datepicker",["mgcrea.ngStrap.helpers.dateParser","mgcrea.ngStrap.tooltip"]).provider("$datepicker",function(){var a=this.defaults={animation:"animation-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",autoclose:!1,minDate:-1/0,maxDate:+1/0,startView:0,minView:0,weekStart:0};this.$get=["$window","$document","$rootScope","$sce","$locale","dateFilter","datepickerViews","$tooltip",function(b,c,d,e,f,g,h,i){function j(b,c,d){function e(a){a.selected=g.$isSelected(a.date)}function f(){b[0].focus()}var g=i(b,angular.extend({},a,d)),j=d.scope,m=g.$options,n=g.$scope,o=h(g);g.$views=o.views;var p=o.viewDate;n.$mode=m.startView;var q=g.$views[n.$mode];n.$select=function(a){g.select(a)},n.$selectPane=function(a){g.$selectPane(a)},n.$toggleMode=function(){g.setMode((n.$mode+1)%g.$views.length)},g.update=function(a){isNaN(a.getTime())?q.built||g.$build():(g.$date=a,q.update.call(q,a))},g.select=function(a,b){angular.isDate(a)||(a=new Date(a)),c.$dateValue.setFullYear(a.getFullYear(),a.getMonth(),a.getDate()),!n.$mode||b?(c.$setViewValue(c.$dateValue),c.$render(),m.autoclose&&!b&&g.hide(!0)):(angular.extend(p,{year:a.getFullYear(),month:a.getMonth(),date:a.getDate()}),g.setMode(n.$mode-1),g.$build())},g.setMode=function(a){n.$mode=a,q=g.$views[n.$mode],g.$build()},g.$build=function(){q.build.call(q)},g.$updateSelected=function(){for(var a=0,b=n.rows.length;b>a;a++)angular.forEach(n.rows[a],e)},g.$isSelected=function(a){return q.isSelected(a)},g.$selectPane=function(a){var b=q.steps,c=new Date(Date.UTC(p.year+(b.year||0)*a,p.month+(b.month||0)*a,p.date+(b.day||0)*a));angular.extend(p,{year:c.getUTCFullYear(),month:c.getUTCMonth(),date:c.getUTCDate()}),g.$build()},g.$onMouseDown=function(a){if(a.preventDefault(),a.stopPropagation(),k){var b=angular.element(a.target);"button"!==b[0].nodeName.toLowerCase()&&(b=b.parent()),b.triggerHandler("click")}},g.$onKeyDown=function(a){if(/(38|37|39|40|13)/.test(a.keyCode)&&!a.shiftKey&&!a.altKey){if(a.preventDefault(),a.stopPropagation(),13===a.keyCode)return n.$mode?n.$apply(function(){g.setMode(n.$mode-1)}):g.hide(!0);q.onKeyDown(a),j.$digest()}};var r=g.init;g.init=function(){return l&&m.useNative?(b.prop("type","date"),void b.css("-webkit-appearance","textfield")):(k&&(b.prop("type","text"),b.attr("readonly","true"),b.on("click",f)),c.$dateValue&&(g.$date=c.$dateValue,g.$build()),void r())};var s=g.destroy;g.destroy=function(){l&&m.useNative&&b.off("click",f),s()};var t=g.show;g.show=function(){t(),setTimeout(function(){g.$element.on(k?"touchstart":"mousedown",g.$onMouseDown),m.keyboard&&b.on("keydown",g.$onKeyDown)})};var u=g.hide;return g.hide=function(a){g.$element.off(k?"touchstart":"mousedown",g.$onMouseDown),m.keyboard&&b.off("keydown",g.$onKeyDown),u(a)},g}var k=(angular.element(b.document.body),"createTouch"in b.document),l=/(iP(a|o)d|iPhone)/g.test(b.navigator.userAgent);return a.lang||(a.lang=f.id),j.defaults=a,j}]}).directive("bsDatepicker",["$window","$parse","$q","$locale","dateFilter","$datepicker","$dateParser","$timeout",function(a,b,c,d,e,f,g){{var h=/(iP(a|o)d|iPhone)/g.test(a.navigator.userAgent);a.requestAnimationFrame||a.setTimeout}return{restrict:"EAC",require:"ngModel",link:function(a,b,c,d){var i={scope:a,controller:d};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","autoclose","dateType","dateFormat","useNative","lang"],function(a){angular.isDefined(c[a])&&(i[a]=c[a])}),h&&i.useNative&&(i.dateFormat="yyyy-MM-dd");var j=f(b,d,i);i=j.$options,angular.forEach(["minDate","maxDate"],function(a){angular.isDefined(c[a])&&c.$observe(a,function(b){if("today"===b){var c=new Date;j.$options[a]=+new Date(c.getFullYear(),c.getMonth(),c.getDate()+("maxDate"===a?1:0),0,0,0,"minDate"===a?0:-1)}else j.$options[a]=angular.isString(b)&&b.match(/^".+"$/)?+new Date(b.substr(1,b.length-2)):+new Date(b);!isNaN(j.$options[a])&&j.$build()})}),a.$watch(c.ngModel,function(){j.update(d.$dateValue)},!0);var k=g({format:i.dateFormat,lang:i.lang});d.$parsers.unshift(function(a){var b=k.parse(a,d.$dateValue);if(!b||isNaN(b.getTime()))d.$setValidity("date",!1);else{var c=b.getTime()>=i.minDate&&b.getTime()<=i.maxDate;d.$setValidity("date",c),c&&(d.$dateValue=b)}return d.$dateValue=b,"string"===i.dateType?e(a,i.dateFormat):"number"===i.dateType?d.$dateValue.getTime():"iso"===i.dateType?d.$dateValue.toISOString():d.$dateValue}),d.$formatters.push(function(a){var b=angular.isDate(a)?a:new Date(a);return d.$dateValue=b,d.$dateValue}),d.$render=function(){b.val(isNaN(d.$dateValue.getTime())?"":e(d.$dateValue,i.dateFormat))},a.$on("$destroy",function(){j.destroy(),i=null,j=null})}}}]).provider("datepickerViews",function(){function a(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c}this.defaults={dayFormat:"dd",daySplit:7};this.$get=["$locale","$sce","dateFilter",function(b,c,d){return function(e){var f=e.$scope,g=e.$options,h=b.DATETIME_FORMATS.SHORTDAY,i=h.slice(g.weekStart).concat(h.slice(0,g.weekStart)),j=c.trustAsHtml(''+i.join(' | ')+" | "),k=e.$date||new Date,l={year:k.getFullYear(),month:k.getMonth(),date:k.getDate()},m=(6e4*k.getTimezoneOffset(),[{format:"dd",split:7,height:250,steps:{month:1},update:function(a,b){!this.built||b||a.getFullYear()!==l.year||a.getMonth()!==l.month?(angular.extend(l,{year:e.$date.getFullYear(),month:e.$date.getMonth(),date:e.$date.getDate()}),e.$build()):a.getDate()!==l.date&&(l.date=e.$date.getDate(),e.$updateSelected())},build:function(){for(var b,c=new Date(l.year,l.month,1),h=new Date(+c-864e5*(c.getUTCDay()+1-g.weekStart)),i=[],k=0;35>k;k++)b=new Date(h.getFullYear(),h.getMonth(),h.getDate()+k),i.push({date:b,label:d(b,this.format),selected:e.$date&&this.isSelected(b),muted:b.getMonth()!==l.month,disabled:this.isDisabled(b)});f.title=d(c,"MMMM yyyy"),f.labels=j,f.rows=a(i,this.split),f.width=100/this.split,f.height=(this.height-75)/f.rows.length,this.built=!0},isSelected:function(a){return e.$date&&a.getFullYear()===e.$date.getFullYear()&&a.getMonth()===e.$date.getMonth()&&a.getDate()===e.$date.getDate()},isDisabled:function(a){return a.getTime()g.maxDate},onKeyDown:function(a){var b=e.$date.getTime();37===a.keyCode?e.select(new Date(b-864e5),!0):38===a.keyCode?e.select(new Date(b-6048e5),!0):39===a.keyCode?e.select(new Date(b+864e5),!0):40===a.keyCode&&e.select(new Date(b+6048e5),!0)}},{name:"month",format:"MMM",split:4,height:250,steps:{year:1},update:function(a){this.built&&a.getFullYear()===l.year?a.getMonth()!==l.month&&(angular.extend(l,{month:e.$date.getMonth(),date:e.$date.getDate()}),e.$updateSelected()):(angular.extend(l,{year:e.$date.getFullYear(),month:e.$date.getMonth(),date:e.$date.getDate()}),e.$build())},build:function(){for(var b,c=(new Date(l.year,0,1),[]),g=0;12>g;g++)b=new Date(l.year,g,1),c.push({date:b,label:d(b,this.format),selected:e.$isSelected(b),disabled:this.isDisabled(b)});f.title=d(b,"yyyy"),f.labels=!1,f.rows=a(c,this.split),f.width=100/this.split,f.height=(this.height-50)/f.rows.length,this.built=!0},isSelected:function(a){return e.$date&&a.getFullYear()===e.$date.getFullYear()&&a.getMonth()===e.$date.getMonth()},isDisabled:function(a){var b=+new Date(a.getFullYear(),a.getMonth()+1,0);return bg.maxDate},onKeyDown:function(a){var b=e.$date.getMonth();37===a.keyCode?e.select(e.$date.setMonth(b-1),!0):38===a.keyCode?e.select(e.$date.setMonth(b-4),!0):39===a.keyCode?e.select(e.$date.setMonth(b+1),!0):40===a.keyCode&&e.select(e.$date.setMonth(b+4),!0)}},{name:"year",format:"yyyy",split:4,height:250,steps:{year:12},update:function(a,b){!this.built||b||parseInt(a.getFullYear()/20,10)!==parseInt(l.year/20,10)?(angular.extend(l,{year:e.$date.getFullYear(),month:e.$date.getMonth(),date:e.$date.getDate()}),e.$build()):a.getFullYear()!==l.year&&(angular.extend(l,{year:e.$date.getFullYear(),month:e.$date.getMonth(),date:e.$date.getDate()}),e.$updateSelected())},build:function(){for(var b,c=l.year-l.year%(3*this.split),g=[],h=0;12>h;h++)b=new Date(c+h,0,1),g.push({date:b,label:d(b,this.format),selected:e.$isSelected(b),disabled:this.isDisabled(b)});f.title=g[0].label+"-"+g[g.length-1].label,f.labels=!1,f.rows=a(g,this.split),f.width=100/this.split,f.height=(this.height-50)/f.rows.length,this.built=!0},isSelected:function(a){return e.$date&&a.getFullYear()===e.$date.getFullYear()},isDisabled:function(a){var b=+new Date(a.getFullYear()+1,0,0);return bg.maxDate},onKeyDown:function(a){var b=e.$date.getFullYear();37===a.keyCode?e.select(e.$date.setYear(b-1),!0):38===a.keyCode?e.select(e.$date.setYear(b-4),!0):39===a.keyCode?e.select(e.$date.setYear(b+1),!0):40===a.keyCode&&e.select(e.$date.setYear(b+4),!0)}}]);return{views:g.minView?Array.prototype.slice.call(m,g.minView):m,viewDate:l}}}]}),angular.module("mgcrea.ngStrap.dropdown",["mgcrea.ngStrap.tooltip"]).provider("$dropdown",function(){var a=this.defaults={animation:"animation-fade",prefixClass:"dropdown",placement:"bottom-left",template:"dropdown/dropdown.tpl.html",trigger:"click",container:!1,keyboard:!0,html:!1,delay:0};this.$get=["$window","$tooltip",function(b,c){function d(b,d){function g(a){return a.target!==b[0]?a.target!==b[0]&&h.hide():void 0}var h={},i=angular.extend({},a,d);h=c(b,i),h.$onKeyDown=function(a){if(/(38|40)/.test(a.keyCode)){a.preventDefault(),a.stopPropagation();var b=angular.element(h.$element[0].querySelectorAll("li:not(.divider) a"));if(b.length){var c;angular.forEach(b,function(a,b){f&&f.call(a,":focus")&&(c=b)}),38===a.keyCode&&c>0?c--:40===a.keyCode&&c1){var g=f.search(c[b]);a=a.split(c[b]).join(""),m[c[b]]&&(d[g]=m[c[b]])}return angular.forEach(d,function(a){e.push(a)}),e}function f(a){return a.replace(/\//g,"[\\/]").replace("/-/g","[-]").replace(/\./g,"[.]").replace(/\\s/g,"[\\s]")}function g(a){var b,c=Object.keys(l),d=a;for(b=0;bj?d=setTimeout(i,b-j):(d=null,c||(h=a.apply(f,e)))},j=c&&!d;return d||(d=setTimeout(i,b)),j&&(h=a.apply(f,e)),h}}).constant("throttle",function(a,b,c){var d,e,f,g=null,h=0;c||(c={});var i=function(){h=c.leading===!1?0:new Date,g=null,f=a.apply(d,e)};return function(){var j=new Date;h||c.leading!==!1||(h=j);var k=b-(j-h);return d=this,e=arguments,0>=k?(clearTimeout(g),g=null,h=j,f=a.apply(d,e)):g||c.trailing===!1||(g=setTimeout(i,k)),f}}),angular.module("mgcrea.ngStrap.helpers.dimensions",[]).factory("dimensions",["$document","$window",function(){var b=(angular.element,{}),c=b.nodeName=function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()};b.css=function(b,c,d){var e;return e=b.currentStyle?b.currentStyle[c]:a.getComputedStyle?a.getComputedStyle(b)[c]:b.style[c],d===!0?parseFloat(e)||0:e},b.offset=function(b){var c=b.getBoundingClientRect(),d=b.ownerDocument;return{width:b.offsetWidth,height:b.offsetHeight,top:c.top+(a.pageYOffset||d.documentElement.scrollTop)-(d.documentElement.clientTop||0),left:c.left+(a.pageXOffset||d.documentElement.scrollLeft)-(d.documentElement.clientLeft||0)}},b.position=function(a){var e,f,g={top:0,left:0};return"fixed"===b.css(a,"position")?f=a.getBoundingClientRect():(e=d(a),f=b.offset(a),f=b.offset(a),c(e,"html")||(g=b.offset(e)),g.top+=b.css(e,"borderTopWidth",!0),g.left+=b.css(e,"borderLeftWidth",!0)),{width:a.offsetWidth,height:a.offsetHeight,top:f.top-g.top-b.css(a,"marginTop",!0),left:f.left-g.left-b.css(a,"marginLeft",!0)}};var d=function(a){var d=a.ownerDocument,e=a.offsetParent||d;if(c(e,"#document"))return d.documentElement;for(;e&&!c(e,"html")&&"static"===b.css(e,"position");)e=e.offsetParent;return e||d.documentElement};return b.height=function(a,c){var d=a.offsetHeight;return c?d+=b.css(a,"marginTop",!0)+b.css(a,"marginBottom",!0):d-=b.css(a,"paddingTop",!0)+b.css(a,"paddingBottom",!0)+b.css(a,"borderTopWidth",!0)+b.css(a,"borderBottomWidth",!0),d},b.width=function(a,c){var d=a.offsetWidth;return c?d+=b.css(a,"marginLeft",!0)+b.css(a,"marginRight",!0):d-=b.css(a,"paddingLeft",!0)+b.css(a,"paddingRight",!0)+b.css(a,"borderLeftWidth",!0)+b.css(a,"borderRightWidth",!0),d},b}]),angular.module("mgcrea.ngStrap.helpers.parseOptions",[]).provider("$parseOptions",function(){var a=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(b,c){function d(d,e){function f(a){return a.map(function(a){var b,c,d={};return d[k]=a,b=j(d),c=n(d),angular.isObject(c)&&(c=b),{label:b,value:c}})}var g={},h=angular.extend({},a,e);g.$values=[];var i,j,k,l,m,n,o;return g.init=function(){g.$match=i=d.match(h.regexp),j=b(i[2]||i[1]),k=i[4]||i[6],l=i[5],m=b(i[3]||""),n=b(i[2]?i[1]:k),o=b(i[7])},g.valuesFn=function(a,b){return c.when(o(a,b)).then(function(a){return g.$values=a?f(a):{},g.$values})},g.init(),g}return d}]}),angular.module("mgcrea.ngStrap.modal",["mgcrea.ngStrap.helpers.dimensions"]).provider("$modal",function(){var a=this.defaults={animation:"animation-fade",prefixClass:"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","dimensions",function(c,d,e,f,g,h,i){function j(b){function c(a){a.target===a.currentTarget&&("static"===q.backdrop?j.focus():j.hide())}var j={},q=angular.extend({},a,b);j.$promise=f.when(g.get(q.template)||h.get(q.template));var r=j.$scope=q.scope&&q.scope.$new()||d.$new();q.element||q.container||(q.container="body"),q.scope||k(["title","content"],function(a){q[a]&&(r[a]=q[a])}),r.$hide=function(){r.$$postDigest(function(){j.hide()})},r.$show=function(){r.$$postDigest(function(){j.show()})},r.$toggle=function(){r.$$postDigest(function(){j.toggle()})},q.contentTemplate&&(j.$promise=j.$promise.then(function(a){angular.isObject(a)&&(a=a.data);var c=angular.element(a);return f.when(g.get(q.contentTemplate)||h.get(q.contentTemplate,{cache:g})).then(function(a){angular.isObject(a)&&(a=a.data);var d=p('[ng-bind="content"]',c[0]).removeAttr("ng-bind").html(a);return b.template||d.next().remove(),c[0].outerHTML})}));var s,t,u=l('');return j.$promise.then(function(a){angular.isObject(a)&&(a=a.data),q.html&&(a=a.replace(o,'ng-bind-html="')),a=m.apply(a),s=e(a),j.init()}),j.init=function(){q.show&&r.$$postDigest(function(){j.show()})},j.destroy=function(){t&&(t.remove(),t=null),u&&(u.remove(),u=null),r.$destroy()},j.show=function(){var a=q.container?p(q.container):null,b=q.container?null:q.element;t=j.$element=s(r,function(){}),t.css({display:"block"}).addClass(q.placement),q.animation&&(q.backdrop&&u.addClass("animation-fade"),t.addClass(q.animation)),q.backdrop&&i.enter(u,n,null,function(){}),i.enter(t,a,b,function(){}),r.$isShown=!0,r.$$phase||r.$digest(),j.focus(),n.addClass(q.prefixClass+"-open"),q.backdrop&&(t.on("click",c),u.on("click",c)),q.keyboard&&t.on("keyup",j.$onKeyUp)},j.hide=function(){i.leave(t,function(){n.removeClass(q.prefixClass+"-open")}),q.backdrop&&i.leave(u,function(){}),r.$$phase||r.$digest(),r.$isShown=!1,q.backdrop&&(t.off("click",c),u.off("click",c)),q.keyboard&&t.off("keyup",j.$onKeyUp)},j.toggle=function(){r.$isShown?j.hide():j.show()},j.focus=function(){t[0].focus()},j.$onKeyUp=function(a){27===a.which&&j.hide()},j}var k=angular.forEach,l=angular.element,m=String.prototype.trim,n=l(c.document.body),o=/ng-bind="/gi,p=function(a,c){return l((c||b).querySelectorAll(a))};return j}]}).directive("bsModal",["$window","$location","$sce","$modal",function(a,b,c,d){return{restrict:"EAC",scope:!0,link:function(a,b,c){var e={scope:a,element:b,show:!1};angular.forEach(["template","contentTemplate","placement","backdrop","keyboard","html","container","animation"],function(a){angular.isDefined(c[a])&&(e[a]=c[a])}),angular.forEach(["title","content"],function(b){c[b]&&c.$observe(b,function(c){a[b]=c})}),c.bsModal&&a.$watch(c.bsModal,function(b){angular.isObject(b)?angular.extend(a,b):a.content=b},!0);var f=d(e);b.on(c.trigger||"click",f.toggle),a.$on("$destroy",function(){f.destroy(),e=null,f=null})}}}]),angular.module("mgcrea.ngStrap.navbar",[]).provider("$navbar",function(){var a=this.defaults={activeClass:"active",routeAttr:"data-match-route"};this.$get=function(){return{defaults:a}}}).directive("bsNavbar",["$window","$location","$navbar",function(a,b,c){var d=c.defaults;return{restrict:"A",link:function(a,c,e){var f=d;angular.forEach(Object.keys(d),function(a){angular.isDefined(e[a])&&(f[a]=e[a])}),a.$watch(function(){return b.path()},function(a){var b=c[0].querySelectorAll("li["+f.routeAttr+"]");angular.forEach(b,function(b){var c=angular.element(b),d=c.attr(f.routeAttr),e=new RegExp("^"+d.replace("/","\\/")+"$",["i"]);e.test(a)?c.addClass(f.activeClass):c.removeClass(f.activeClass)})})}}}]),angular.module("mgcrea.ngStrap.popover",["mgcrea.ngStrap.tooltip"]).provider("$popover",function(){var a=this.defaults={animation:"animation-fade",placement:"right",template:"popover/popover.tpl.html",contentTemplate:!1,trigger:"click",keyboard:!0,html:!1,title:"",content:"",delay:0,container:!1};this.$get=["$tooltip",function(b){function c(c,d){var e=angular.extend({},a,d),f=b(c,e);return e.content&&(f.$scope.content=e.content),f}return c}]}).directive("bsPopover",["$window","$location","$sce","$popover",function(a,b,c,d){var e=a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",scope:!0,link:function(a,b,c){var f={scope:a};angular.forEach(["template","contentTemplate","placement","container","delay","trigger","keyboard","html","animation"],function(a){angular.isDefined(c[a])&&(f[a]=c[a])}),angular.forEach(["title","content"],function(b){c[b]&&c.$observe(b,function(c,d){a[b]=c,angular.isDefined(d)&&e(function(){g&&g.$applyPlacement()})})}),c.bsPopover&&a.$watch(c.bsPopover,function(b,c){angular.isObject(b)?angular.extend(a,b):a.content=b,angular.isDefined(c)&&e(function(){g&&g.$applyPlacement()})},!0);var g=d(b,f);a.$on("$destroy",function(){g.destroy(),f=null,g=null})}}}]),angular.module("mgcrea.ngStrap.scrollspy",["mgcrea.ngStrap.helpers.debounce","mgcrea.ngStrap.helpers.dimensions"]).provider("$scrollspy",function(){var a=this.$$spies={},c=this.defaults={debounce:150,throttle:100,offset:100};this.$get=["$window","$document","$rootScope","dimensions","debounce","throttle",function(d,e,f,g,h,i){function j(a,b){return a[0].nodeName&&a[0].nodeName.toLowerCase()===b.toLowerCase()}function k(e){var k=angular.extend({},c,e);k.element||(k.element=n);var o=j(k.element,"body"),p=o?l:k.element,q=o?"window":k.id;if(a[q])return a[q].$$count++,a[q];var r,s,t,u,v,w,x={},y=x.$trackedElements=[],z=[];return x.init=function(){this.$$count=1,s=h(this.checkPosition,k.debounce),t=i(this.checkPosition,k.throttle),p.on("click",this.checkPositionWithEventLoop),l.on("resize",s),p.on("scroll",t),u=h(this.checkOffsets,k.debounce),f.$on("$viewContentLoaded",u),f.$on("$includeContentLoaded",u),u(),q&&(a[q]=x)},x.destroy=function(){this.$$count--,this.$$count>0||(p.off("click",this.checkPositionWithEventLoop),l.off("resize",s),p.off("scroll",s),f.$off("$viewContentLoaded",u),f.$off("$includeContentLoaded",u))},x.checkPosition=function(){if(z.length){if(w=(o?d.pageYOffset:p.prop("scrollTop"))||0,v=Math.max(d.innerHeight,m.prop("clientHeight")),wz[a+1].offsetTop))return x.$activateElement(z[a])}},x.checkPositionWithEventLoop=function(){setTimeout(this.checkPosition,1)},x.$activateElement=function(a){if(r){var b=x.$getTrackedElement(r);b&&(b.source.removeClass("active"),j(b.source,"li")&&j(b.source.parent().parent(),"li")&&b.source.parent().parent().removeClass("active"))}r=a.target,a.source.addClass("active"),j(a.source,"li")&&j(a.source.parent().parent(),"li")&&a.source.parent().parent().addClass("active")},x.$getTrackedElement=function(a){return y.filter(function(b){return b.target===a})[0]},x.checkOffsets=function(){angular.forEach(y,function(a){var c=b.querySelector(a.target);a.offsetTop=c?g.offset(c).top:null,k.offset&&null!==a.offsetTop&&(a.offsetTop-=1*k.offset)}),z=y.filter(function(a){return null!==a.offsetTop}).sort(function(a,b){return a.offsetTop-b.offsetTop}),s()},x.trackElement=function(a,b){y.push({target:a,source:b})},x.untrackElement=function(a,b){for(var c,d=y.length;d--;)if(y[d].target===a&&y[d].source===b){c=d;break}y=y.splice(c,1)},x.activate=function(a){y[a].addClass("active")},x.init(),x}var l=angular.element(d),m=angular.element(e.prop("documentElement")),n=angular.element(d.document.body);return k}]}).directive("bsScrollspy",["$rootScope","debounce","dimensions","$scrollspy",function(a,b,c,d){return{restrict:"EAC",link:function(a,b,c){var e={scope:a};angular.forEach(["offset","target"],function(a){angular.isDefined(c[a])&&(e[a]=c[a])});var f=d(e);f.trackElement(e.target,b),a.$on("$destroy",function(){f.untrackElement(e.target,b),f.destroy(),e=null,f=null})}}}]).directive("bsScrollspyList",["$rootScope","debounce","dimensions","$scrollspy",function(){return{restrict:"A",compile:function(a){var b=a[0].querySelectorAll("li > a[href]");
+angular.forEach(b,function(a){var b=angular.element(a);b.parent().attr("bs-scrollspy","").attr("data-target",b.attr("href"))})}}}]),angular.module("mgcrea.ngStrap.select",["mgcrea.ngStrap.tooltip","mgcrea.ngStrap.helpers.parseOptions"]).provider("$select",function(){var a=this.defaults={animation:"animation-fade",prefixClass:"select",placement:"bottom-left",template:"select/select.tpl.html",trigger:"focus",container:!1,keyboard:!0,html:!1,delay:0,multiple:!1,sort:!0,caretHtml:' ',placeholder:"Choose among the following..."};this.$get=["$window","$document","$rootScope","$tooltip",function(b,c,d,e){function f(b,c,d){var f={},h=angular.extend({},a,d);f=e(b,h);var i=d.scope,j=f.$scope;j.$matches=[],j.$activeIndex=0,j.$isMultiple=h.multiple,j.$activate=function(a){j.$$postDigest(function(){f.activate(a)})},j.$select=function(a){j.$$postDigest(function(){f.select(a)})},j.$isVisible=function(){return f.$isVisible()},j.$isActive=function(a){return f.$isActive(a)},f.update=function(a){j.$matches=a,c.$modelValue&&a.length?j.$activeIndex=h.multiple&&angular.isArray(c.$modelValue)?c.$modelValue.map(function(a){return f.$getIndex(a)}):f.$getIndex(c.$modelValue):j.$activeIndex>=a.length&&(j.$activeIndex=h.multiple?[]:0)},f.activate=function(a){return h.multiple?(j.$activeIndex.sort(),f.$isActive(a)?j.$activeIndex.splice(j.$activeIndex.indexOf(a),1):j.$activeIndex.push(a),h.sort&&j.$activeIndex.sort()):j.$activeIndex=a,j.$activeIndex},f.select=function(a){var d=j.$matches[a].value;f.activate(a),c.$setViewValue(h.multiple?j.$activeIndex.map(function(a){return j.$matches[a].value}):d),c.$render(),i&&i.$digest(),h.multiple||("focus"===h.trigger?b[0].blur():f.$isShown&&f.hide()),j.$emit("$select.select",d,a)},f.$isVisible=function(){return h.minLength&&c?j.$matches.length&&c.$viewValue.length>=h.minLength:j.$matches.length},f.$isActive=function(a){return h.multiple?-1!==j.$activeIndex.indexOf(a):j.$activeIndex===a},f.$getIndex=function(a){var b=j.$matches.length,c=b;if(b){for(c=b;c--&&j.$matches[c].value!==a;);if(!(0>c))return c}},f.$onElementMouseDown=function(a){a.preventDefault(),a.stopPropagation(),f.$isShown?b[0].blur():b[0].focus()},f.$onMouseDown=function(a){if(a.preventDefault(),a.stopPropagation(),g){var b=angular.element(a.target);b.triggerHandler("click")}},f.$onKeyDown=function(a){if(/(38|40|13)/.test(a.keyCode)){if(a.preventDefault(),a.stopPropagation(),13===a.keyCode)return f.select(j.$activeIndex);38===a.keyCode&&j.$activeIndex>0?j.$activeIndex--:40===a.keyCode&&j.$activeIndexb?b+12:b-12),c.$render()},l.$build=function(){var a,b,c=o.midIndex=parseInt(n.length/2,10),d=[];for(a=0;an.maxTime},l.$moveIndex=function(a,b){var c;0===b?(c=new Date(1970,0,1,r.hour+a*n.length,r.minute),angular.extend(r,{hour:c.getHours()})):1===b&&(c=new Date(1970,0,1,r.hour,r.minute+a*n.length*5),angular.extend(r,{minute:c.getMinutes()})),l.$build()},l.$onMouseDown=function(a){if("input"!==a.target.nodeName.toLowerCase()&&a.preventDefault(),a.stopPropagation(),j){var b=angular.element(a.target);"button"!==b[0].nodeName.toLowerCase()&&(b=b.parent()),b.triggerHandler("click")}},l.$onKeyDown=function(a){if(/(38|37|39|40|13)/.test(a.keyCode)&&!a.shiftKey&&!a.altKey){if(a.preventDefault(),a.stopPropagation(),13===a.keyCode)return l.hide(!0);var b=new Date(l.$date),c=b.getHours(),d=g(b,"h").length,f=b.getMinutes(),h=g(b,"mm").length,i=/(37|39)/.test(a.keyCode),j=2+1*!!t[2];if(i&&(37===a.keyCode?p=1>p?j-1:p-1:39===a.keyCode&&(p=j-1>p?p+1:0)),0===p){if(i)return e(0,d);38===a.keyCode?b.setHours(c-n.hourStep):40===a.keyCode&&b.setHours(c+n.hourStep)}else if(1===p){if(i)return e(d+1,d+1+h);38===a.keyCode?b.setMinutes(f-n.minuteStep):40===a.keyCode&&b.setMinutes(f+n.minuteStep)}else if(2===p){if(i)return e(d+1+h+1,d+1+h+3);l.switchMeridian()}l.select(b,p,!0),m.$digest()}};var u=l.init;l.init=function(){j&&(b.prop("type","text"),b.attr("readonly","true"),b.on("click",i)),u()};var v=l.destroy;l.destroy=function(){k&&n.useNative&&b.off("click",i),v()};var w=l.show;l.show=function(){w(),setTimeout(function(){l.$element.on(j?"touchstart":"mousedown",l.$onMouseDown),n.keyboard&&b.on("keydown",l.$onKeyDown)})};var x=l.hide;return l.hide=function(a){l.$element.off(j?"touchstart":"mousedown",l.$onMouseDown),n.keyboard&&b.off("keydown",l.$onKeyDown),x(a)},l}var j=(angular.element(b.document.body),"createTouch"in b.document),k=/(iP(a|o)d|iPhone)/g.test(b.navigator.userAgent);return a.lang||(a.lang=f.id),i.defaults=a,i}]}).directive("bsTimepicker",["$window","$parse","$q","$locale","dateFilter","$timepicker","$dateParser","$timeout",function(a,b,c,d,e,f,g){a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",require:"ngModel",link:function(a,b,c,d){var h={scope:a,controller:d};angular.forEach(["placement","container","delay","trigger","keyboard","html","animation","template","autoclose","timeType","timeFormat","useNative","lang"],function(a){angular.isDefined(c[a])&&(h[a]=c[a])});var i=f(b,d,h);h=i.$options;var j=g({format:h.timeFormat,lang:h.lang});angular.forEach(["minTime","maxTime"],function(a){angular.isDefined(c[a])&&c.$observe(a,function(b){i.$options[a]="now"===b?(new Date).setFullYear(1970,0,1):angular.isString(b)&&b.match(/^".+"$/)?+new Date(b.substr(1,b.length-2)):j.parse(b),!isNaN(i.$options[a])&&i.$build()})}),a.$watch(c.ngModel,function(){i.update(d.$dateValue)},!0),d.$parsers.unshift(function(a){var b=j.parse(a,d.$dateValue);if(!b||isNaN(b.getTime()))d.$setValidity("date",!1);else{var c=b.getTime()>=h.minTime&&b.getTime()<=h.maxTime;d.$setValidity("date",c),c&&(d.$dateValue=b)}return"string"===h.timeType?e(a,h.timeFormat):"number"===h.timeType?d.$dateValue.getTime():"iso"===h.timeType?d.$dateValue.toISOString():d.$dateValue}),d.$formatters.push(function(a){var b=angular.isDate(a)?a:new Date(a);return isNaN(b.getTime())&&(b=new Date((new Date).setMinutes(0)+36e5)),d.$dateValue=b,d.$dateValue}),d.$render=function(){b.val(isNaN(d.$dateValue.getTime())?"":e(d.$dateValue,h.timeFormat))},a.$on("$destroy",function(){i.destroy(),h=null,i=null})}}}]),angular.module("mgcrea.ngStrap.tooltip",["mgcrea.ngStrap.helpers.dimensions"]).provider("$tooltip",function(){var a=this.defaults={animation:"animation-fade",prefixClass:"tooltip",container:!1,placement:"top",template:"tooltip/tooltip.tpl.html",contentTemplate:!1,trigger:"hover focus",keyboard:!1,html:!1,show:!1,title:"",type:"",delay:0};this.$get=["$window","$rootScope","$compile","$q","$templateCache","$http","$animate","$timeout","dimensions",function(c,d,e,f,g,h,i,j,k){function l(b,c){function j(){return"body"===r.container?k.offset(b[0]):k.position(b[0])}function l(a,b,c,d){var e,f=a.split("-");switch(f[0]){case"right":e={top:b.top+b.height/2-d/2,left:b.left+b.width};break;case"bottom":e={top:b.top+b.height,left:b.left+b.width/2-c/2};break;case"left":e={top:b.top+b.height/2-d/2,left:b.left-c};break;default:e={top:b.top-d,left:b.left+b.width/2-c/2}}if(!f[1])return e;if("top"===f[0]||"bottom"===f[0])switch(f[1]){case"left":e.left=b.left;break;case"right":e.left=b.left+b.width-c}else if("left"===f[0]||"right"===f[0])switch(f[1]){case"top":e.top=b.top-d;break;case"bottom":e.top=b.top+b.height}return e}var q={},r=q.$options=angular.extend({},a,c);q.$promise=f.when(g.get(r.template)||h.get(r.template));var s=q.$scope=r.scope&&r.scope.$new()||d.$new();r.delay&&angular.isString(r.delay)&&(r.delay=parseFloat(r.delay)),r.title&&(q.$scope.title=r.title),s.$hide=function(){s.$$postDigest(function(){q.hide()})},s.$show=function(){s.$$postDigest(function(){q.show()})},s.$toggle=function(){s.$$postDigest(function(){q.toggle()})},q.$isShown=!1;var t,u;r.contentTemplate&&(q.$promise=q.$promise.then(function(a){angular.isObject(a)&&(a=a.data);var b=angular.element(a);return f.when(g.get(r.contentTemplate)||h.get(r.contentTemplate,{cache:g})).then(function(a){return angular.isObject(a)&&(a=a.data),p('[ng-bind="content"]',b[0]).removeAttr("ng-bind").html(a),b[0].outerHTML})}));var v,w,x;return q.$promise.then(function(a){angular.isObject(a)&&(a=a.data),r.html&&(a=a.replace(o,'ng-bind-html="')),a=m.apply(a),x=a,v=e(a),q.init()}),q.init=function(){r.delay&&angular.isNumber(r.delay)&&(r.delay={show:r.delay,hide:r.delay});for(var a=r.trigger.split(" "),c=a.length;c--;){var d=a[c];"click"===d?b.on("click",q.toggle):"manual"!==d&&(b.on("hover"===d?"mouseenter":"focus",q.enter),b.on("hover"===d?"mouseleave":"blur",q.leave))}r.show&&s.$$postDigest(function(){"focus"===r.trigger?b[0].focus():q.show()})},q.destroy=function(){for(var a=r.trigger.split(" "),c=a.length;c--;){var d=a[c];"click"===d?b.off("click",q.toggle):"manual"!==d&&(b.off("hover"===d?"mouseenter":"focus",q.enter),b.off("hover"===d?"mouseleave":"blur",q.leave))}w&&(w.remove(),w=null),s.$destroy()},q.enter=function(){return clearTimeout(t),u="in",r.delay&&r.delay.show?void(t=setTimeout(function(){"in"===u&&q.show()},r.delay.show)):q.show()},q.show=function(){var a=r.container?p(r.container):null,c=r.container?null:b;w=q.$element=v(s,function(){}),w.css({top:"0px",left:"0px",display:"block"}).addClass(r.placement),r.animation&&w.addClass(r.animation),r.type&&w.addClass(r.prefixClass+"-"+r.type),i.enter(w,a,c,function(){}),q.$isShown=!0,s.$$phase||s.$digest(),n(q.$applyPlacement),r.keyboard&&("focus"!==r.trigger?(q.focus(),w.on("keyup",q.$onKeyUp)):b.on("keyup",q.$onFocusKeyUp))},q.leave=function(){return q.$isShown?(clearTimeout(t),u="out",r.delay&&r.delay.hide?void(t=setTimeout(function(){"out"===u&&q.hide()},r.delay.hide)):q.hide()):void 0},q.hide=function(a){return i.leave(w,function(){}),s.$$phase||s.$digest(),q.$isShown=!1,r.keyboard&&w.off("keyup",q.$onKeyUp),a&&"focus"===r.trigger?b[0].blur():void 0},q.toggle=function(){q.$isShown?q.leave():q.enter()},q.focus=function(){w[0].focus()},q.$applyPlacement=function(){if(w){var a=j(),b=w.prop("offsetWidth"),c=w.prop("offsetHeight"),d=l(r.placement,a,b,c);d.top+="px",d.left+="px",w.css(d)}},q.$onKeyUp=function(a){27===a.which&&q.hide()},q.$onFocusKeyUp=function(a){27===a.which&&b[0].blur()},q}var m=String.prototype.trim,n=c.requestAnimationFrame||c.setTimeout,o=/ng-bind="/gi,p=function(a,c){return angular.element((c||b).querySelectorAll(a))};return l}]}).directive("bsTooltip",["$window","$location","$sce","$tooltip",function(a,b,c,d){var e=a.requestAnimationFrame||a.setTimeout;return{restrict:"EAC",scope:!0,link:function(a,b,c){var f={scope:a};angular.forEach(["template","contentTemplate","placement","container","delay","trigger","keyboard","html","animation","type"],function(a){angular.isDefined(c[a])&&(f[a]=c[a])}),angular.forEach(["title"],function(b){c[b]&&c.$observe(b,function(c,d){a[b]=c,angular.isDefined(d)&&e(function(){g&&g.$applyPlacement()})})}),c.bsTooltip&&a.$watch(c.bsTooltip,function(b,c){angular.isObject(b)?angular.extend(a,b):a.content=b,angular.isDefined(c)&&e(function(){g&&g.$applyPlacement()})},!0);var g=d(b,f);a.$on("$destroy",function(){g.destroy(),f=null,g=null})}}}]),angular.module("mgcrea.ngStrap.typeahead",["mgcrea.ngStrap.tooltip","mgcrea.ngStrap.helpers.parseOptions"]).provider("$typeahead",function(){var a=this.defaults={animation:"animation-fade",prefixClass:"typeahead",placement:"bottom-left",template:"typeahead/typeahead.tpl.html",trigger:"focus",container:!1,keyboard:!0,html:!1,delay:0,minLength:1,limit:6};this.$get=["$window","$rootScope","$tooltip",function(b,c,d){function e(b,c){var e={},f=angular.extend({},a,c),g=f.controller;e=d(b,f);var h=c.scope,i=e.$scope;i.$matches=[],i.$activeIndex=0,i.$activate=function(a){i.$$postDigest(function(){e.activate(a)})},i.$select=function(a){i.$$postDigest(function(){e.select(a)})},i.$isVisible=function(){return e.$isVisible()},e.update=function(a){i.$matches=a,i.$activeIndex>=a.length&&(i.$activeIndex=0)},e.activate=function(a){i.$activeIndex=a},e.select=function(a){var c=i.$matches[a].value;g&&(g.$setViewValue(c),g.$render(),h&&h.$digest()),"focus"===f.trigger?b[0].blur():e.$isShown&&e.hide(),i.$activeIndex=0,i.$emit("$typeahead.select",c,a)},e.$isVisible=function(){return f.minLength&&g?i.$matches.length&&angular.isString(g.$viewValue)&&g.$viewValue.length>=f.minLength:!!i.$matches.length},e.$onMouseDown=function(a){a.preventDefault(),a.stopPropagation()},e.$onKeyDown=function(a){if(/(38|40|13)/.test(a.keyCode)){if(a.preventDefault(),a.stopPropagation(),13===a.keyCode)return e.select(i.$activeIndex);38===a.keyCode&&i.$activeIndex>0?i.$activeIndex--:40===a.keyCode&&i.$activeIndexi&&(a=a.slice(0,i)),k.update(a)})}),a.$on("$destroy",function(){k.destroy(),h=null,k=null})}}}])}(window,document),function(){"use strict";angular.module("mgcrea.ngStrap.aside").run(["$templateCache",function(a){a.put("aside/aside.tpl.html",'')}]),angular.module("mgcrea.ngStrap.datepicker").run(["$templateCache",function(a){a.put("datepicker/datepicker.tpl.html",'')}]),angular.module("mgcrea.ngStrap.dropdown").run(["$templateCache",function(a){a.put("dropdown/dropdown.tpl.html",'')}]),angular.module("mgcrea.ngStrap.modal").run(["$templateCache",function(a){a.put("modal/modal.tpl.html",'')}]),angular.module("mgcrea.ngStrap.popover").run(["$templateCache",function(a){a.put("popover/popover.tpl.html",'')}]),angular.module("mgcrea.ngStrap.select").run(["$templateCache",function(a){a.put("select/select.tpl.html",'')}]),angular.module("mgcrea.ngStrap.tab").run(["$templateCache",function(a){a.put("tab/tab.tpl.html",'')}]),angular.module("mgcrea.ngStrap.timepicker").run(["$templateCache",function(a){a.put("timepicker/timepicker.tpl.html",'')}]),angular.module("mgcrea.ngStrap.tooltip").run(["$templateCache",function(a){a.put("tooltip/tooltip.tpl.html",'')}]),angular.module("mgcrea.ngStrap.typeahead").run(["$templateCache",function(a){a.put("typeahead/typeahead.tpl.html",'')}])}(window,document);
+//# sourceMappingURL=angular-strap.min.map
\ No newline at end of file
diff --git a/ajax/libs/angular-strap/package.json b/ajax/libs/angular-strap/package.json
index 84d952c78..a1163c98f 100644
--- a/ajax/libs/angular-strap/package.json
+++ b/ajax/libs/angular-strap/package.json
@@ -2,7 +2,7 @@
"name": "angular-strap",
"filename": "angular-strap.min.js",
"description": "AngularStrap - Twitter Bootstrap directives for AngularJS.",
- "version": "0.7.5",
+ "version": "2.0.0-rc.1",
"homepage": "http://mgcrea.github.com/angular-strap",
"keywords": [
"angular",