diff --git a/bower.json b/bower.json index 680997ffb..6654e9bea 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "angular-strap", "description": "AngularStrap - AngularJS directives for Bootstrap", - "version": "2.2.2", + "version": "2.2.3", "keywords": [ "angular", "bootstrap" diff --git a/dist/angular-strap.js b/dist/angular-strap.js index 6e75855f0..9f0e3641e 100644 --- a/dist/angular-strap.js +++ b/dist/angular-strap.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT @@ -182,6 +182,125 @@ } ] }; }); + 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', '$$rAF', function($button, $$rAF) { + 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; + }); + controller.$formatters.push(function(modelValue) { + return angular.equals(modelValue, trueValue); + }); + scope.$watch(attr.ngModel, function(newValue, oldValue) { + controller.$render(); + }); + } + controller.$render = function() { + var isActive = angular.equals(controller.$modelValue, trueValue); + $$rAF(function() { + 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', '$$rAF', function($button, $$rAF) { + 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; + attr.$observe('value', function(v) { + value = constantValueRegExp.test(v) ? scope.$eval(v) : v; + controller.$render(); + }); + controller.$render = function() { + var isActive = angular.equals(controller.$modelValue, value); + $$rAF(function() { + 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.alert', [ 'mgcrea.ngStrap.modal' ]).provider('$alert', function() { var defaults = this.defaults = { animation: 'am-fade', @@ -327,125 +446,6 @@ } }; } ]); - 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', '$$rAF', function($button, $$rAF) { - 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; - }); - controller.$formatters.push(function(modelValue) { - return angular.equals(modelValue, trueValue); - }); - scope.$watch(attr.ngModel, function(newValue, oldValue) { - controller.$render(); - }); - } - controller.$render = function() { - var isActive = angular.equals(controller.$modelValue, trueValue); - $$rAF(function() { - 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', '$$rAF', function($button, $$rAF) { - 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; - attr.$observe('value', function(v) { - value = constantValueRegExp.test(v) ? scope.$eval(v) : v; - controller.$render(); - }); - controller.$render = function() { - var isActive = angular.equals(controller.$modelValue, value); - $$rAF(function() { - 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.collapse', []).provider('$collapse', function() { var defaults = this.defaults = { animation: 'am-collapse', @@ -491,7 +491,7 @@ self.$targets.$active = !self.$options.startCollapsed ? [ 0 ] : []; self.$setActive = $scope.$setActive = function(value) { if (angular.isArray(value)) { - self.$targets.$active = angular.copy(value); + self.$targets.$active = value; } else if (!self.$options.disallowToggle) { isActive(value) ? deactivateItem(value) : activateItem(value); } else { @@ -2576,6 +2576,134 @@ } }; } ]); + angular.module('mgcrea.ngStrap.tab', []).provider('$tab', function() { + var defaults = this.defaults = { + animation: 'am-fade', + template: 'tab/tab.tpl.html', + navClass: 'nav-tabs', + activeClass: 'active' + }; + var controller = this.controller = function($scope, $element, $attrs) { + var self = this; + self.$options = angular.copy(defaults); + angular.forEach([ 'animation', 'navClass', 'activeClass' ], function(key) { + if (angular.isDefined($attrs[key])) self.$options[key] = $attrs[key]; + }); + $scope.$navClass = self.$options.navClass; + $scope.$activeClass = self.$options.activeClass; + self.$panes = $scope.$panes = []; + self.$activePaneChangeListeners = self.$viewChangeListeners = []; + self.$push = function(pane) { + if (angular.isUndefined(self.$panes.$active)) { + $scope.$setActive(pane.name || 0); + } + self.$panes.push(pane); + }; + self.$remove = function(pane) { + var index = self.$panes.indexOf(pane); + var active = self.$panes.$active; + var activeIndex; + if (angular.isString(active)) { + activeIndex = self.$panes.map(function(pane) { + return pane.name; + }).indexOf(active); + } else { + activeIndex = self.$panes.$active; + } + self.$panes.splice(index, 1); + if (index < activeIndex) { + activeIndex--; + } else if (index === activeIndex && activeIndex === self.$panes.length) { + activeIndex--; + } + if (activeIndex >= 0 && activeIndex < self.$panes.length) { + self.$setActive(self.$panes[activeIndex].name || activeIndex); + } else { + self.$setActive(); + } + }; + self.$setActive = $scope.$setActive = function(value) { + self.$panes.$active = value; + self.$activePaneChangeListeners.forEach(function(fn) { + fn(); + }); + }; + self.$isActive = $scope.$isActive = function($pane, $index) { + return self.$panes.$active === $pane.name || self.$panes.$active === $index; + }; + }; + this.$get = function() { + var $tab = {}; + $tab.defaults = defaults; + $tab.controller = controller; + return $tab; + }; + }).directive('bsTabs', [ '$window', '$animate', '$tab', '$parse', function($window, $animate, $tab, $parse) { + var defaults = $tab.defaults; + return { + require: [ '?ngModel', 'bsTabs' ], + transclude: true, + scope: true, + controller: [ '$scope', '$element', '$attrs', $tab.controller ], + templateUrl: function(element, attr) { + return attr.template || defaults.template; + }, + link: function postLink(scope, element, attrs, controllers) { + var ngModelCtrl = controllers[0]; + var bsTabsCtrl = controllers[1]; + if (ngModelCtrl) { + bsTabsCtrl.$activePaneChangeListeners.push(function() { + ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active); + }); + ngModelCtrl.$formatters.push(function(modelValue) { + bsTabsCtrl.$setActive(modelValue); + return modelValue; + }); + } + if (attrs.bsActivePane) { + var parsedBsActivePane = $parse(attrs.bsActivePane); + bsTabsCtrl.$activePaneChangeListeners.push(function() { + parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active); + }); + scope.$watch(attrs.bsActivePane, function(newValue, oldValue) { + bsTabsCtrl.$setActive(newValue); + }, true); + } + } + }; + } ]).directive('bsPane', [ '$window', '$animate', '$sce', function($window, $animate, $sce) { + return { + require: [ '^?ngModel', '^bsTabs' ], + scope: true, + link: function postLink(scope, element, attrs, controllers) { + var ngModelCtrl = controllers[0]; + var bsTabsCtrl = controllers[1]; + element.addClass('tab-pane'); + attrs.$observe('title', function(newValue, oldValue) { + scope.title = $sce.trustAsHtml(newValue); + }); + scope.name = attrs.name; + if (bsTabsCtrl.$options.animation) { + element.addClass(bsTabsCtrl.$options.animation); + } + attrs.$observe('disabled', function(newValue, oldValue) { + scope.disabled = scope.$eval(newValue); + }); + bsTabsCtrl.$push(scope); + scope.$on('$destroy', function() { + bsTabsCtrl.$remove(scope); + }); + function render() { + var index = bsTabsCtrl.$panes.indexOf(scope); + $animate[bsTabsCtrl.$isActive(scope, index) ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass); + } + bsTabsCtrl.$activePaneChangeListeners.push(function() { + render(); + }); + render(); + } + }; + } ]); angular.module('mgcrea.ngStrap.timepicker', [ 'mgcrea.ngStrap.helpers.dateParser', 'mgcrea.ngStrap.helpers.dateFormatter', 'mgcrea.ngStrap.tooltip' ]).provider('$timepicker', function() { var defaults = this.defaults = { animation: 'am-fade', @@ -3018,117 +3146,6 @@ } }; } ]); - angular.module('mgcrea.ngStrap.tab', []).provider('$tab', function() { - var defaults = this.defaults = { - animation: 'am-fade', - template: 'tab/tab.tpl.html', - navClass: 'nav-tabs', - activeClass: 'active' - }; - var controller = this.controller = function($scope, $element, $attrs) { - var self = this; - self.$options = angular.copy(defaults); - angular.forEach([ 'animation', 'navClass', 'activeClass' ], function(key) { - if (angular.isDefined($attrs[key])) self.$options[key] = $attrs[key]; - }); - $scope.$navClass = self.$options.navClass; - $scope.$activeClass = self.$options.activeClass; - self.$panes = $scope.$panes = []; - self.$activePaneChangeListeners = self.$viewChangeListeners = []; - self.$push = function(pane) { - self.$panes.push(pane); - }; - self.$remove = function(pane) { - var index = self.$panes.indexOf(pane); - var activeIndex = self.$panes.$active; - self.$panes.splice(index, 1); - if (index < activeIndex) { - activeIndex--; - } else if (index === activeIndex && activeIndex === self.$panes.length) { - activeIndex--; - } - self.$setActive(activeIndex); - }; - self.$panes.$active = 0; - self.$setActive = $scope.$setActive = function(value) { - self.$panes.$active = value; - self.$activePaneChangeListeners.forEach(function(fn) { - fn(); - }); - }; - }; - this.$get = function() { - var $tab = {}; - $tab.defaults = defaults; - $tab.controller = controller; - return $tab; - }; - }).directive('bsTabs', [ '$window', '$animate', '$tab', '$parse', function($window, $animate, $tab, $parse) { - var defaults = $tab.defaults; - return { - require: [ '?ngModel', 'bsTabs' ], - transclude: true, - scope: true, - controller: [ '$scope', '$element', '$attrs', $tab.controller ], - templateUrl: function(element, attr) { - return attr.template || defaults.template; - }, - link: function postLink(scope, element, attrs, controllers) { - var ngModelCtrl = controllers[0]; - var bsTabsCtrl = controllers[1]; - if (ngModelCtrl) { - bsTabsCtrl.$activePaneChangeListeners.push(function() { - ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active); - }); - ngModelCtrl.$formatters.push(function(modelValue) { - bsTabsCtrl.$setActive(modelValue * 1); - return modelValue; - }); - } - if (attrs.bsActivePane) { - var parsedBsActivePane = $parse(attrs.bsActivePane); - bsTabsCtrl.$activePaneChangeListeners.push(function() { - parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active); - }); - scope.$watch(attrs.bsActivePane, function(newValue, oldValue) { - bsTabsCtrl.$setActive(newValue * 1); - }, true); - } - } - }; - } ]).directive('bsPane', [ '$window', '$animate', '$sce', function($window, $animate, $sce) { - return { - require: [ '^?ngModel', '^bsTabs' ], - scope: true, - link: function postLink(scope, element, attrs, controllers) { - var ngModelCtrl = controllers[0]; - var bsTabsCtrl = controllers[1]; - element.addClass('tab-pane'); - attrs.$observe('title', function(newValue, oldValue) { - scope.title = $sce.trustAsHtml(newValue); - }); - if (bsTabsCtrl.$options.animation) { - element.addClass(bsTabsCtrl.$options.animation); - } - attrs.$observe('disabled', function(newValue, oldValue) { - scope.disabled = scope.$eval(newValue); - }); - bsTabsCtrl.$push(scope); - scope.$on('$destroy', function() { - bsTabsCtrl.$remove(scope); - }); - function render() { - var index = bsTabsCtrl.$panes.indexOf(scope); - var active = bsTabsCtrl.$panes.$active; - $animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass); - } - bsTabsCtrl.$activePaneChangeListeners.push(function() { - render(); - }); - render(); - } - }; - } ]); angular.module('mgcrea.ngStrap.tooltip', [ 'mgcrea.ngStrap.helpers.dimensions' ]).provider('$tooltip', function() { var defaults = this.defaults = { animation: 'am-fade', diff --git a/dist/angular-strap.min.js b/dist/angular-strap.min.js index b31714aaa..df63500bf 100644 --- a/dist/angular-strap.min.js +++ b/dist/angular-strap.min.js @@ -1,11 +1,11 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT */ -!function(e,t,n){'use strict';angular.module('mgcrea.ngStrap',['mgcrea.ngStrap.modal','mgcrea.ngStrap.aside','mgcrea.ngStrap.alert','mgcrea.ngStrap.button','mgcrea.ngStrap.select','mgcrea.ngStrap.datepicker','mgcrea.ngStrap.timepicker','mgcrea.ngStrap.navbar','mgcrea.ngStrap.tooltip','mgcrea.ngStrap.popover','mgcrea.ngStrap.dropdown','mgcrea.ngStrap.typeahead','mgcrea.ngStrap.scrollspy','mgcrea.ngStrap.affix','mgcrea.ngStrap.tab','mgcrea.ngStrap.collapse']),angular.module('mgcrea.ngStrap.affix',['mgcrea.ngStrap.helpers.dimensions','mgcrea.ngStrap.helpers.debounce']).provider('$affix',function(){var e=this.defaults={offsetTop:'auto',inlineStyles:!0};this.$get=['$window','debounce','dimensions',function(t,n,a){function o(o,s){function l(e,t,n){var a=u(),o=c();return v>=a?'top':null!==e&&a+e<=t.top?'middle':null!==w&&t.top+n+$>=o-w?'bottom':'middle'}function u(){return p[0]===t?t.pageYOffset:p[0].scrollTop}function c(){return p[0]===t?t.document.body.scrollHeight:p[0].scrollHeight}var d={},f=angular.extend({},e,s),p=f.target,g='affix affix-top affix-bottom',m=!1,$=0,h=0,v=0,w=0,y=null,b=null,D=o.parent();if(f.offsetParent)if(f.offsetParent.match(/^\d+$/))for(var k=0;k<1*f.offsetParent-1;k++)D=D.parent();else D=angular.element(f.offsetParent);return d.init=function(){this.$parseOffsets(),h=a.offset(o[0]).top+$,m=!o[0].style.width,p.on('scroll',this.checkPosition),p.on('click',this.checkPositionWithEventLoop),r.on('resize',this.$debouncedOnResize),this.checkPosition(),this.checkPositionWithEventLoop()},d.destroy=function(){p.off('scroll',this.checkPosition),p.off('click',this.checkPositionWithEventLoop),r.off('resize',this.$debouncedOnResize)},d.checkPositionWithEventLoop=function(){setTimeout(d.checkPosition,1)},d.checkPosition=function(){var e=u(),t=a.offset(o[0]),n=a.height(o[0]),r=l(b,t,n);y!==r&&(y=r,o.removeClass(g).addClass('affix'+('middle'!==r?'-'+r:'')),'top'===r?(b=null,m&&o.css('width',''),f.inlineStyles&&(o.css('position',f.offsetParent?'':'relative'),o.css('top',''))):'bottom'===r?(b=f.offsetUnpin?-(1*f.offsetUnpin):t.top-e,m&&o.css('width',''),f.inlineStyles&&(o.css('position',f.offsetParent?'':'relative'),o.css('top',f.offsetParent?'':i[0].offsetHeight-w-n-h+'px'))):(b=null,m&&o.css('width',o[0].offsetWidth+'px'),f.inlineStyles&&(o.css('position','fixed'),o.css('top',$+'px'))))},d.$onResize=function(){d.$parseOffsets(),d.checkPosition()},d.$debouncedOnResize=n(d.$onResize,50),d.$parseOffsets=function(){var e=o.css('position');f.inlineStyles&&o.css('position',f.offsetParent?'':'relative'),f.offsetTop&&('auto'===f.offsetTop&&(f.offsetTop='+0'),f.offsetTop.match(/^[-+]\d+$/)?($=1*-f.offsetTop,v=f.offsetParent?a.offset(D[0]).top+1*f.offsetTop:a.offset(o[0]).top-a.css(o[0],'marginTop',!0)+1*f.offsetTop):v=1*f.offsetTop),f.offsetBottom&&(w=f.offsetParent&&f.offsetBottom.match(/^[-+]\d+$/)?c()-(a.offset(D[0]).top+a.height(D[0]))+1*f.offsetBottom+1:1*f.offsetBottom),f.inlineStyles&&o.css('position',e)},d.init(),d}var i=angular.element(t.document.body),r=angular.element(t);return o}]}).directive('bsAffix',['$affix','$window',function(e,t){return{restrict:'EAC',require:'^?bsAffixTarget',link:function(n,a,o,i){var r={scope:n,target:i?i.$element:angular.element(t)};angular.forEach(['offsetTop','offsetBottom','offsetParent','offsetUnpin','inlineStyles'],function(e){if(angular.isDefined(o[e])){var t=o[e];/true/i.test(t)&&(t=!0),/false/i.test(t)&&(t=!1),r[e]=t}});var s=e(a,r);n.$on('$destroy',function(){s&&s.destroy(),r=null,s=null})}}}]).directive('bsAffixTarget',function(){return{controller:['$element',function(e){this.$element=e}]}}),angular.module('mgcrea.ngStrap.alert',['mgcrea.ngStrap.modal']).provider('$alert',function(){var e=this.defaults={animation:'am-fade',prefixClass:'alert',prefixEvent:'alert',placement:null,template:'alert/alert.tpl.html',container:!1,element:null,backdrop:!1,keyboard:!0,show:!0,duration:!1,type:!1,dismissable:!0};this.$get=['$modal','$timeout',function(t,n){function a(a){var o={},i=angular.extend({},e,a);o=t(i),o.$scope.dismissable=!!i.dismissable,i.type&&(o.$scope.type=i.type);var r=o.show;return i.duration&&(o.show=function(){r(),n(function(){o.hide()},1e3*i.duration)}),o}return a}]}).directive('bsAlert',['$window','$sce','$alert',function(e,t,n){e.requestAnimationFrame||e.setTimeout;return{restrict:'EAC',scope:!0,link:function(e,a,o,i){var r={scope:e,element:a,show:!1};angular.forEach(['template','placement','keyboard','html','container','animation','duration','dismissable'],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var s=/^(false|0|)$/i;angular.forEach(['keyboard','html','container','dismissable'],function(e){angular.isDefined(o[e])&&s.test(o[e])&&(r[e]=!1)}),e.hasOwnProperty('title')||(e.title=''),angular.forEach(['title','content','type'],function(n){o[n]&&o.$observe(n,function(a,o){e[n]=t.trustAsHtml(a)})}),o.bsAlert&&e.$watch(o.bsAlert,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var l=n(r);a.on(o.trigger||'click',l.toggle),e.$on('$destroy',function(){l&&l.destroy(),r=null,l=null})}}}]),angular.module('mgcrea.ngStrap.aside',['mgcrea.ngStrap.modal']).provider('$aside',function(){var e=this.defaults={animation:'am-fade-and-slide-right',prefixClass:'aside',prefixEvent:'aside',placement:'right',template:'aside/aside.tpl.html',contentTemplate:!1,container:!1,element:null,backdrop:!0,keyboard:!0,html:!1,show:!0};this.$get=['$modal',function(t){function n(n){var a={},o=angular.extend({},e,n);return a=t(o)}return n}]}).directive('bsAside',['$window','$sce','$aside',function(e,t,n){e.requestAnimationFrame||e.setTimeout;return{restrict:'EAC',scope:!0,link:function(e,a,o,i){var r={scope:e,element:a,show:!1};angular.forEach(['template','contentTemplate','placement','backdrop','keyboard','html','container','animation'],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var s=/^(false|0|)$/i;angular.forEach(['backdrop','keyboard','html','container'],function(e){angular.isDefined(o[e])&&s.test(o[e])&&(r[e]=!1)}),angular.forEach(['title','content'],function(n){o[n]&&o.$observe(n,function(a,o){e[n]=t.trustAsHtml(a)})}),o.bsAside&&e.$watch(o.bsAside,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var l=n(r);a.on(o.trigger||'click',l.toggle),e.$on('$destroy',function(){l&&l.destroy(),r=null,l=null})}}}]),angular.module('mgcrea.ngStrap.button',[]).provider('$button',function(){var e=this.defaults={activeClass:'active',toggleEvent:'click'};this.$get=function(){return{defaults:e}}}).directive('bsCheckboxGroup',function(){return{restrict:'A',require:'ngModel',compile:function(e,t){e.attr('data-toggle','buttons'),e.removeAttr('ng-model');var n=e[0].querySelectorAll('input[type="checkbox"]');angular.forEach(n,function(e){var n=angular.element(e);n.attr('bs-checkbox',''),n.attr('ng-model',t.ngModel+'.'+n.attr('value'))})}}}).directive('bsCheckbox',['$button','$$rAF',function(e,t){var n=e.defaults,a=/^(true|false|\d+)$/;return{restrict:'A',require:'ngModel',link:function(e,o,i,r){var s=n,l='INPUT'===o[0].nodeName,u=l?o.parent():o,c=angular.isDefined(i.trueValue)?i.trueValue:!0;a.test(i.trueValue)&&(c=e.$eval(i.trueValue));var d=angular.isDefined(i.falseValue)?i.falseValue:!1;a.test(i.falseValue)&&(d=e.$eval(i.falseValue));var f='boolean'!=typeof c||'boolean'!=typeof d;f&&(r.$parsers.push(function(e){return e?c:d}),r.$formatters.push(function(e){return angular.equals(e,c)}),e.$watch(i.ngModel,function(e,t){r.$render()})),r.$render=function(){var e=angular.equals(r.$modelValue,c);t(function(){l&&(o[0].checked=e),u.toggleClass(s.activeClass,e)})},o.bind(s.toggleEvent,function(){e.$apply(function(){l||r.$setViewValue(!u.hasClass('active')),f||r.$render()})})}}}]).directive('bsRadioGroup',function(){return{restrict:'A',require:'ngModel',compile:function(e,t){e.attr('data-toggle','buttons'),e.removeAttr('ng-model');var n=e[0].querySelectorAll('input[type="radio"]');angular.forEach(n,function(e){angular.element(e).attr('bs-radio',''),angular.element(e).attr('ng-model',t.ngModel)})}}}).directive('bsRadio',['$button','$$rAF',function(e,t){var n=e.defaults,a=/^(true|false|\d+)$/;return{restrict:'A',require:'ngModel',link:function(e,o,i,r){var s,l=n,u='INPUT'===o[0].nodeName,c=u?o.parent():o;i.$observe('value',function(t){s=a.test(t)?e.$eval(t):t,r.$render()}),r.$render=function(){var e=angular.equals(r.$modelValue,s);t(function(){u&&(o[0].checked=e),c.toggleClass(l.activeClass,e)})},o.bind(l.toggleEvent,function(){e.$apply(function(){r.$setViewValue(s),r.$render()})})}}}]),angular.module('mgcrea.ngStrap.collapse',[]).provider('$collapse',function(){var e=this.defaults={animation:'am-collapse',disallowToggle:!1,activeClass:'in',startCollapsed:!1,allowMultiple:!1},t=this.controller=function(t,n,a){function o(e){for(var t=l.$targets.$active,n=0;nt;t++)angular.forEach(g.rows[t],u.$setDisabledEl)},u.select=function(e,t){angular.isDate(n.$dateValue)||(n.$dateValue=new Date(e)),!g.$mode||t?(n.$setViewValue(angular.copy(e)),n.$render(),p.autoclose&&!t&&l(function(){u.hide(!0)})):(angular.extend($,{year:e.getFullYear(),month:e.getMonth(),date:e.getDate()}),u.setMode(g.$mode-1),u.$build())},u.setMode=function(e){g.$mode=e,h=u.$views[g.$mode],u.$build()},u.$build=function(e){e===!0&&h.built||(e!==!1||h.built)&&h.build.call(h)},u.$updateSelected=function(){for(var e=0,t=g.rows.length;t>e;e++)angular.forEach(g.rows[e],o)},u.$isSelected=function(e){return h.isSelected(e)},u.$setDisabledEl=function(e){e.disabled=h.isDisabled(e.date)},u.$selectPane=function(e){var t=h.steps,n=new Date(Date.UTC($.year+(t.year||0)*e,$.month+(t.month||0)*e,1));angular.extend($,{year:n.getUTCFullYear(),month:n.getUTCMonth(),date:n.getUTCDate()}),u.$build()},u.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),d){var t=angular.element(e.target);'button'!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler('click')}},u.$onKeyDown=function(e){if(/(38|37|39|40|13)/.test(e.keyCode)&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),e.stopPropagation(),13===e.keyCode)return g.$mode?g.$apply(function(){u.setMode(g.$mode-1)}):u.hide(!0);h.onKeyDown(e),f.$digest()}};var v=u.init;u.init=function(){return c&&p.useNative?(t.prop('type','date'),void t.css('-webkit-appearance','textfield')):(d&&(t.prop('type','text'),t.attr('readonly','true'),t.on('click',i)),void v())};var w=u.destroy;u.destroy=function(){c&&p.useNative&&t.off('click',i),w()};var y=u.show;u.show=function(){y(),l(function(){u.$isShown&&(u.$element.on(d?'touchstart':'mousedown',u.$onMouseDown),p.keyboard&&t.on('keydown',u.$onKeyDown))},0,!1)};var b=u.hide;return u.hide=function(e){u.$isShown&&(u.$element.off(d?'touchstart':'mousedown',u.$onMouseDown),p.keyboard&&t.off('keydown',u.$onKeyDown),b(e))},u}var c=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),d='createTouch'in t.document&&c;return e.lang||(e.lang=i.getDefaultLocale()),u.defaults=e,u}]}).directive('bsDatepicker',['$window','$parse','$q','$dateFormatter','$dateParser','$datepicker',function(e,t,n,a,o,i){var r=(i.defaults,/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent));return{restrict:'EAC',require:'ngModel',link:function(e,t,n,s){function l(e){return e&&e.length?e:null}function u(e){if(angular.isDate(e)){var t=isNaN(p.$options.minDate)||e.getTime()>=p.$options.minDate,n=isNaN(p.$options.maxDate)||e.getTime()<=p.$options.maxDate,a=t&&n;s.$setValidity('date',a),s.$setValidity('min',t),s.$setValidity('max',n),a&&(s.$dateValue=e)}}function c(){return!s.$dateValue||isNaN(s.$dateValue.getTime())?'':m(s.$dateValue,d.dateFormat)}var d={scope:e,controller:s};angular.forEach(['placement','container','delay','trigger','html','animation','template','autoclose','dateType','dateFormat','timezone','modelDateFormat','dayFormat','strictFormat','startWeek','startDate','useNative','lang','startView','minView','iconLeft','iconRight','daysOfWeekDisabled','id','prefixClass','prefixEvent'],function(e){angular.isDefined(n[e])&&(d[e]=n[e])});var f=/^(false|0|)$/i;angular.forEach(['html','container','autoclose','useNative'],function(e){angular.isDefined(n[e])&&f.test(n[e])&&(d[e]=!1)}),n.bsShow&&e.$watch(n.bsShow,function(e,t){p&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(datepicker),?/i)),e===!0?p.show():p.hide())});var p=i(t,s,d);d=p.$options,r&&d.useNative&&(d.dateFormat='yyyy-MM-dd');var g=d.lang,m=function(e,t){return a.formatDate(e,t,g)},$=o({format:d.dateFormat,lang:g,strict:d.strictFormat});angular.forEach(['minDate','maxDate'],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){p.$options[e]=$.getDateForAttribute(e,t),!isNaN(p.$options[e])&&p.$build(!1),u(s.$dateValue)})}),e.$watch(n.ngModel,function(e,t){p.update(s.$dateValue)},!0),angular.isDefined(n.disabledDates)&&e.$watch(n.disabledDates,function(e,t){e=l(e),t=l(t),e&&p.updateDisabledDates(e)}),s.$parsers.unshift(function(e){var t;if(!e)return s.$setValidity('date',!0),null;var n=$.parse(e,s.$dateValue);return!n||isNaN(n.getTime())?void s.$setValidity('date',!1):(u(n),'string'===d.dateType?(t=$.timezoneOffsetAdjust(n,d.timezone,!0),m(t,d.modelDateFormat||d.dateFormat)):(t=$.timezoneOffsetAdjust(s.$dateValue,d.timezone,!0),'number'===d.dateType?t.getTime():'unix'===d.dateType?t.getTime()/1e3:'iso'===d.dateType?t.toISOString():new Date(t)))}),s.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:'string'===d.dateType?$.parse(e,null,d.modelDateFormat):new Date('unix'===d.dateType?1e3*e:e),s.$dateValue=$.timezoneOffsetAdjust(t,d.timezone),c()}),s.$render=function(){t.val(c())},e.$on('$destroy',function(){p&&p.destroy(),d=null,p=null})}}}]).provider('datepickerViews',function(){function e(e,t){for(var n=[];e.length>0;)n.push(e.splice(0,t));return n}function t(e,t){return(e%t+t)%t}this.defaults={dayFormat:'dd',daySplit:7};this.$get=['$dateFormatter','$dateParser','$sce',function(n,a,o){return function(i){var r=i.$scope,s=i.$options,l=s.lang,u=function(e,t){return n.formatDate(e,t,l)},c=a({format:s.dateFormat,lang:l,strict:s.strictFormat}),d=n.weekdaysShort(l),f=d.slice(s.startWeek).concat(d.slice(0,s.startWeek)),p=o.trustAsHtml(''+f.join('')+''),g=i.$date||(s.startDate?c.getDateForAttribute('startDate',s.startDate):new Date),m={year:g.getFullYear(),month:g.getMonth(),date:g.getDate()},$=[{format:s.dayFormat,split:7,steps:{month:1},update:function(e,t){!this.built||t||e.getFullYear()!==m.year||e.getMonth()!==m.month?(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build()):(e.getDate()!==m.date||1===e.getDate())&&(m.date=i.$date.getDate(),i.$updateSelected())},build:function(){var n=new Date(m.year,m.month,1),a=n.getTimezoneOffset(),o=new Date(+n-864e5*t(n.getDay()-s.startWeek,7)),l=o.getTimezoneOffset(),d=c.timezoneOffsetAdjust(new Date,s.timezone).toDateString();l!==a&&(o=new Date(+o+6e4*(l-a)));for(var f,g=[],$=0;42>$;$++)f=c.daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth(),o.getDate()+$)),g.push({date:f,isToday:f.toDateString()===d,label:u(f,this.format),selected:i.$date&&this.isSelected(f),muted:f.getMonth()!==m.month,disabled:this.isDisabled(f)});r.title=u(n,s.monthTitleFormat),r.showLabels=!0,r.labels=p,r.rows=e(g,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()&&e.getMonth()===i.$date.getMonth()&&e.getDate()===i.$date.getDate()},isDisabled:function(e){var t=e.getTime();if(ts.maxDate)return!0;if(-1!==s.daysOfWeekDisabled.indexOf(e.getDay()))return!0;if(s.disabledDateRanges)for(var n=0;n=s.disabledDateRanges[n].start&&t<=s.disabledDateRanges[n].end)return!0;return!1},onKeyDown:function(e){if(i.$date){var t,n=i.$date.getTime();37===e.keyCode?t=new Date(n-864e5):38===e.keyCode?t=new Date(n-6048e5):39===e.keyCode?t=new Date(n+864e5):40===e.keyCode&&(t=new Date(n+6048e5)),this.isDisabled(t)||i.select(t,!0)}}},{name:'month',format:s.monthFormat,split:4,steps:{year:1},update:function(e,t){this.built&&e.getFullYear()===m.year?e.getMonth()!==m.month&&(angular.extend(m,{month:i.$date.getMonth(),date:i.$date.getDate()}),i.$updateSelected()):(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build())},build:function(){for(var t,n=(new Date(m.year,0,1),[]),a=0;12>a;a++)t=new Date(m.year,a,1),n.push({date:t,label:u(t,this.format),selected:i.$isSelected(t),disabled:this.isDisabled(t)});r.title=u(t,s.yearTitleFormat),r.showLabels=!1,r.rows=e(n,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()&&e.getMonth()===i.$date.getMonth()},isDisabled:function(e){var t=+new Date(e.getFullYear(),e.getMonth()+1,0);return ts.maxDate},onKeyDown:function(e){if(i.$date){var t=i.$date.getMonth(),n=new Date(i.$date);37===e.keyCode?n.setMonth(t-1):38===e.keyCode?n.setMonth(t-4):39===e.keyCode?n.setMonth(t+1):40===e.keyCode&&n.setMonth(t+4),this.isDisabled(n)||i.select(n,!0)}}},{name:'year',format:s.yearFormat,split:4,steps:{year:12},update:function(e,t){!this.built||t||parseInt(e.getFullYear()/20,10)!==parseInt(m.year/20,10)?(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build()):e.getFullYear()!==m.year&&(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$updateSelected())},build:function(){for(var t,n=m.year-m.year%(3*this.split),a=[],o=0;12>o;o++)t=new Date(n+o,0,1),a.push({date:t,label:u(t,this.format),selected:i.$isSelected(t),disabled:this.isDisabled(t)});r.title=a[0].label+'-'+a[a.length-1].label,r.showLabels=!1,r.rows=e(a,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()},isDisabled:function(e){var t=+new Date(e.getFullYear()+1,0,0);return ts.maxDate},onKeyDown:function(e){if(i.$date){var t=i.$date.getFullYear(),n=new Date(i.$date);37===e.keyCode?n.setYear(t-1):38===e.keyCode?n.setYear(t-4):39===e.keyCode?n.setYear(t+1):40===e.keyCode&&n.setYear(t+4),this.isDisabled(n)||i.select(n,!0)}}}];return{views:s.minView?Array.prototype.slice.call($,s.minView):$,viewDate:m}}}]}),angular.module('mgcrea.ngStrap.dropdown',['mgcrea.ngStrap.tooltip']).provider('$dropdown',function(){var e=this.defaults={animation:'am-fade',prefixClass:'dropdown',prefixEvent:'dropdown',placement:'bottom-left',template:'dropdown/dropdown.tpl.html',trigger:'click',container:!1,keyboard:!0,html:!1,delay:0};this.$get=['$window','$rootScope','$tooltip','$timeout',function(t,n,a,o){function i(t,i){function l(e){return e.target!==t[0]?e.target!==t[0]&&u.hide():void 0}{var u={},c=angular.extend({},e,i);u.$scope=c.scope&&c.scope.$new()||n.$new()}u=a(t,c);var d=t.parent();u.$onKeyDown=function(e){if(/(38|40)/.test(e.keyCode)){e.preventDefault(),e.stopPropagation();var t=angular.element(u.$element[0].querySelectorAll('li:not(.divider) a'));if(t.length){var n;angular.forEach(t,function(e,t){s&&s.call(e,':focus')&&(n=t)}),38===e.keyCode&&n>0?n--:40===e.keyCode&&no;o++)if(e[o].toLowerCase()===a)return o;return-1}t.prototype.setMilliseconds=function(e){this.milliseconds=e},t.prototype.setSeconds=function(e){this.seconds=e},t.prototype.setMinutes=function(e){this.minutes=e},t.prototype.setHours=function(e){this.hours=e},t.prototype.getHours=function(){return this.hours},t.prototype.setDate=function(e){this.day=e},t.prototype.setMonth=function(e){this.month=e},t.prototype.setFullYear=function(e){this.year=e},t.prototype.fromDate=function(e){return this.year=e.getFullYear(),this.month=e.getMonth(),this.day=e.getDate(),this.hours=e.getHours(),this.minutes=e.getMinutes(),this.seconds=e.getSeconds(),this.milliseconds=e.getMilliseconds(),this},t.prototype.toDate=function(){return new Date(this.year,this.month,this.day,this.hours,this.minutes,this.seconds,this.milliseconds)};var i=t.prototype,r=this.defaults={format:'shortDate',strict:!1};this.$get=['$locale','dateFilter',function(e,s){var l=function(l){function u(e){var t,n=Object.keys(h),a=[],o=[],i=e;for(t=0;t1){var r=i.search(n[t]);e=e.split(n[t]).join(''),h[n[t]]&&(a[r]=h[n[t]])}return angular.forEach(a,function(e){e&&o.push(e)}),o}function c(e){return e.replace(/\//g,'[\\/]').replace('/-/g','[-]').replace(/\./g,'[.]').replace(/\\s/g,'[\\s]')}function d(e){var t,n=Object.keys($),a=e;for(t=0;t12?e.getHours()+2:0),e):null},m.timezoneOffsetAdjust=function(e,t,n){return e?(t&&'UTC'===t&&(e=new Date(e.getTime()),e.setMinutes(e.getMinutes()+(n?-1:1)*e.getTimezoneOffset())),e):null},m.init(),m};return l}]}]),angular.module('mgcrea.ngStrap.helpers.debounce',[]).factory('debounce',['$timeout',function(e){return function(t,n,a){var o=null;return function(){var i=this,r=arguments,s=a&&!o;return o&&e.cancel(o),o=e(function(){o=null,a||t.apply(i,r)},n,!1),s&&t.apply(i,r),o}}}]).factory('throttle',['$timeout',function(e){return function(t,n,a){var o=null;return a||(a={}),function(){var i=this,r=arguments;o||(a.leading!==!1&&t.apply(i,r),o=e(function(){o=null,a.trailing!==!1&&t.apply(i,r)},n,!1))}}}]),angular.module('mgcrea.ngStrap.helpers.dimensions',[]).factory('dimensions',['$document','$window',function(t,n){var a=(angular.element,{}),o=a.nodeName=function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()};a.css=function(t,n,a){var o;return o=t.currentStyle?t.currentStyle[n]:e.getComputedStyle?e.getComputedStyle(t)[n]:t.style[n],a===!0?parseFloat(o)||0:o},a.offset=function(t){var n=t.getBoundingClientRect(),a=t.ownerDocument;return{width:n.width||t.offsetWidth,height:n.height||t.offsetHeight,top:n.top+(e.pageYOffset||a.documentElement.scrollTop)-(a.documentElement.clientTop||0),left:n.left+(e.pageXOffset||a.documentElement.scrollLeft)-(a.documentElement.clientLeft||0)}},a.setOffset=function(e,t,n){var o,i,r,s,l,u,c,d=a.css(e,'position'),f=angular.element(e),p={};'static'===d&&(e.style.position='relative'),l=a.offset(e),r=a.css(e,'top'),u=a.css(e,'left'),c=('absolute'===d||'fixed'===d)&&(r+u).indexOf('auto')>-1,c?(o=a.position(e),s=o.top,i=o.left):(s=parseFloat(r)||0,i=parseFloat(u)||0),angular.isFunction(t)&&(t=t.call(e,n,l)), -null!==t.top&&(p.top=t.top-l.top+s),null!==t.left&&(p.left=t.left-l.left+i),'using'in t?t.using.call(f,p):f.css({top:p.top+'px',left:p.left+'px'})},a.position=function(e){var t,n,r={top:0,left:0};return'fixed'===a.css(e,'position')?n=e.getBoundingClientRect():(t=i(e),n=a.offset(e),o(t,'html')||(r=a.offset(t)),r.top+=a.css(t,'borderTopWidth',!0),r.left+=a.css(t,'borderLeftWidth',!0)),{width:e.offsetWidth,height:e.offsetHeight,top:n.top-r.top-a.css(e,'marginTop',!0),left:n.left-r.left-a.css(e,'marginLeft',!0)}};var i=function(e){var t=e.ownerDocument,n=e.offsetParent||t;if(o(n,'#document'))return t.documentElement;for(;n&&!o(n,'html')&&'static'===a.css(n,'position');)n=n.offsetParent;return n||t.documentElement};return a.height=function(e,t){var n=e.offsetHeight;return t?n+=a.css(e,'marginTop',!0)+a.css(e,'marginBottom',!0):n-=a.css(e,'paddingTop',!0)+a.css(e,'paddingBottom',!0)+a.css(e,'borderTopWidth',!0)+a.css(e,'borderBottomWidth',!0),n},a.width=function(e,t){var n=e.offsetWidth;return t?n+=a.css(e,'marginLeft',!0)+a.css(e,'marginRight',!0):n-=a.css(e,'paddingLeft',!0)+a.css(e,'paddingRight',!0)+a.css(e,'borderLeftWidth',!0)+a.css(e,'borderRightWidth',!0),n},a}]),angular.module('mgcrea.ngStrap.helpers.parseOptions',[]).provider('$parseOptions',function(){var e=this.defaults={regexp:/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/};this.$get=['$parse','$q',function(t,n){function a(a,o){function i(e,t){return e.map(function(e,n){var a,o,i={};return i[c]=e,a=u(t,i),o=p(t,i),{label:a,value:o,index:n}})}var r={},s=angular.extend({},e,o);r.$values=[];var l,u,c,d,f,p,g;return r.init=function(){r.$match=l=a.match(s.regexp),u=t(l[2]||l[1]),c=l[4]||l[6],d=l[5],f=t(l[3]||''),p=t(l[2]?l[1]:c),g=t(l[7])},r.valuesFn=function(e,t){return n.when(g(e,t)).then(function(t){return r.$values=t?i(t,e):{},r.$values})},r.displayValue=function(e){var t={};return t[c]=e,u(t)},r.init(),r}return a}]}),angular.version.minor<3&&angular.version.dot<14&&angular.module('ng').factory('$$rAF',['$window','$timeout',function(e,t){var n=e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame,a=e.cancelAnimationFrame||e.webkitCancelAnimationFrame||e.mozCancelAnimationFrame||e.webkitCancelRequestAnimationFrame,o=!!n,i=o?function(e){var t=n(e);return function(){a(t)}}:function(e){var n=t(e,16.66,!1);return function(){t.cancel(n)}};return i.supported=o,i}]),angular.module('mgcrea.ngStrap.modal',['mgcrea.ngStrap.helpers.dimensions']).provider('$modal',function(){var e=this.defaults={animation:'am-fade',backdropAnimation:'am-fade',prefixClass:'modal',prefixEvent:'modal',placement:'top',template:'modal/modal.tpl.html',contentTemplate:!1,container:!1,element:null,backdrop:!0,keyboard:!0,html:!1,show:!0};this.$get=['$window','$rootScope','$compile','$q','$templateCache','$http','$animate','$timeout','$sce','dimensions',function(n,a,o,i,r,s,l,u,c,d){function f(t){function n(){f.$emit(d.prefixEvent+'.show',u)}function i(){f.$emit(d.prefixEvent+'.hide',u),w.removeClass(d.prefixClass+'-open'),d.animation&&w.removeClass(d.prefixClass+'-with-'+d.animation)}function r(e){e.target===e.currentTarget&&('static'===d.backdrop?u.focus():u.hide())}function s(e){e.preventDefault()}var u={},d=u.$options=angular.extend({},e,t);u.$promise=m(d.template);var f=u.$scope=d.scope&&d.scope.$new()||a.$new();d.element||d.container||(d.container='body'),u.$id=d.id||d.element&&d.element.attr('id')||'',$(['title','content'],function(e){d[e]&&(f[e]=c.trustAsHtml(d[e]))}),f.$hide=function(){f.$$postDigest(function(){u.hide()})},f.$show=function(){f.$$postDigest(function(){u.show()})},f.$toggle=function(){f.$$postDigest(function(){u.toggle()})},u.$isShown=f.$isShown=!1,d.contentTemplate&&(u.$promise=u.$promise.then(function(e){var n=angular.element(e);return m(d.contentTemplate).then(function(e){var a=g('[ng-bind="content"]',n[0]).removeAttr('ng-bind').html(e);return t.template||a.next().remove(),n[0].outerHTML})}));var b,D,k=angular.element('
');return k.css({position:'fixed',top:'0px',left:'0px',bottom:'0px',right:'0px','z-index':1038}),u.$promise.then(function(e){angular.isObject(e)&&(e=e.data),d.html&&(e=e.replace(y,'ng-bind-html="')),e=h.apply(e),b=o(e),u.init()}),u.init=function(){d.show&&f.$$postDigest(function(){u.show()})},u.destroy=function(){D&&(D.remove(),D=null),k&&(k.remove(),k=null),f.$destroy()},u.show=function(){if(!u.$isShown){var e,t;if(angular.isElement(d.container)?(e=d.container,t=d.container[0].lastChild?angular.element(d.container[0].lastChild):null):d.container?(e=g(d.container),t=e[0]&&e[0].lastChild?angular.element(e[0].lastChild):null):(e=null,t=d.element),D=u.$element=b(f,function(e,t){}),!f.$emit(d.prefixEvent+'.show.before',u).defaultPrevented){D.css({display:'block'}).addClass(d.placement),d.animation&&(d.backdrop&&k.addClass(d.backdropAnimation),D.addClass(d.animation)),d.backdrop&&l.enter(k,w,null);var a=l.enter(D,e,t,n);a&&a.then&&a.then(n),u.$isShown=f.$isShown=!0,p(f);var o=D[0];v(function(){o.focus()}),w.addClass(d.prefixClass+'-open'),d.animation&&w.addClass(d.prefixClass+'-with-'+d.animation),d.backdrop&&(D.on('click',r),k.on('click',r),k.on('wheel',s)),d.keyboard&&D.on('keyup',u.$onKeyUp)}}},u.hide=function(){if(u.$isShown&&!f.$emit(d.prefixEvent+'.hide.before',u).defaultPrevented){var e=l.leave(D,i);e&&e.then&&e.then(i),d.backdrop&&l.leave(k),u.$isShown=f.$isShown=!1,p(f),d.backdrop&&(D.off('click',r),k.off('click',r),k.off('wheel',s)),d.keyboard&&D.off('keyup',u.$onKeyUp)}},u.toggle=function(){u.$isShown?u.hide():u.show()},u.focus=function(){D[0].focus()},u.$onKeyUp=function(e){27===e.which&&u.$isShown&&(u.hide(),e.stopPropagation())},u}function p(e){e.$$phase||e.$root&&e.$root.$$phase||e.$digest()}function g(e,n){return angular.element((n||t).querySelectorAll(e))}function m(e){return b[e]?b[e]:b[e]=s.get(e,{cache:r}).then(function(e){return e.data})}var $=angular.forEach,h=String.prototype.trim,v=n.requestAnimationFrame||n.setTimeout,w=angular.element(n.document.body),y=/ng-bind="/gi,b={};return f}]}).directive('bsModal',['$window','$sce','$modal',function(e,t,n){return{restrict:'EAC',scope:!0,link:function(e,a,o,i){var r={scope:e,element:a,show:!1};angular.forEach(['template','contentTemplate','placement','backdrop','keyboard','html','container','animation','id','prefixEvent','prefixClass'],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var s=/^(false|0|)$/i;angular.forEach(['backdrop','keyboard','html','container'],function(e){angular.isDefined(o[e])&&s.test(o[e])&&(r[e]=!1)}),angular.forEach(['title','content'],function(n){o[n]&&o.$observe(n,function(a,o){e[n]=t.trustAsHtml(a)})}),o.bsModal&&e.$watch(o.bsModal,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var l=n(r);a.on(o.trigger||'click',l.toggle),e.$on('$destroy',function(){l&&l.destroy(),r=null,l=null})}}}]),angular.module('mgcrea.ngStrap.navbar',[]).provider('$navbar',function(){var e=this.defaults={activeClass:'active',routeAttr:'data-match-route',strict:!1};this.$get=function(){return{defaults:e}}}).directive('bsNavbar',['$window','$location','$navbar',function(e,t,n){var a=n.defaults;return{restrict:'A',link:function(e,n,o,i){var r=angular.copy(a);angular.forEach(Object.keys(a),function(e){angular.isDefined(o[e])&&(r[e]=o[e])}),e.$watch(function(){return t.path()},function(e,t){var a=n[0].querySelectorAll('li['+r.routeAttr+']');angular.forEach(a,function(t){var n=angular.element(t),a=n.attr(r.routeAttr).replace('/','\\/');r.strict&&(a='^'+a+'$');var o=new RegExp(a,'i');o.test(e)?n.addClass(r.activeClass):n.removeClass(r.activeClass)})})}}}]),angular.module('mgcrea.ngStrap.popover',['mgcrea.ngStrap.tooltip']).provider('$popover',function(){var e=this.defaults={animation:'am-fade',customClass:'',container:!1,target:!1,placement:'right',template:'popover/popover.tpl.html',contentTemplate:!1,trigger:'click',keyboard:!0,html:!1,title:'',content:'',delay:0,autoClose:!1};this.$get=['$tooltip',function(t){function n(n,a){var o=angular.extend({},e,a),i=t(n,o);return o.content&&(i.$scope.content=o.content),i}return n}]}).directive('bsPopover',['$window','$sce','$popover',function(e,t,n){var a=e.requestAnimationFrame||e.setTimeout;return{restrict:'EAC',scope:!0,link:function(e,o,i){var r={scope:e};angular.forEach(['template','contentTemplate','placement','container','delay','trigger','html','animation','customClass','autoClose','id','prefixClass','prefixEvent'],function(e){angular.isDefined(i[e])&&(r[e]=i[e])});var s=/^(false|0|)$/i;angular.forEach(['html','container','autoClose'],function(e){angular.isDefined(i[e])&&s.test(i[e])&&(r[e]=!1)});var l=o.attr('data-target');angular.isDefined(l)&&(r.target=s.test(l)?!1:l),angular.forEach(['title','content'],function(n){i[n]&&i.$observe(n,function(o,i){e[n]=t.trustAsHtml(o),angular.isDefined(i)&&a(function(){u&&u.$applyPlacement()})})}),i.bsPopover&&e.$watch(i.bsPopover,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t,angular.isDefined(n)&&a(function(){u&&u.$applyPlacement()})},!0),i.bsShow&&e.$watch(i.bsShow,function(e,t){u&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(popover),?/i)),e===!0?u.show():u.hide())}),i.viewport&&e.$watch(i.viewport,function(e){u&&angular.isDefined(e)&&u.setViewport(e)});var u=n(o,r);e.$on('$destroy',function(){u&&u.destroy(),r=null,u=null})}}}]),angular.module('mgcrea.ngStrap.scrollspy',['mgcrea.ngStrap.helpers.debounce','mgcrea.ngStrap.helpers.dimensions']).provider('$scrollspy',function(){var e=this.$$spies={},n=this.defaults={debounce:150,throttle:100,offset:100};this.$get=['$window','$document','$rootScope','dimensions','debounce','throttle',function(a,o,i,r,s,l){function u(e,t){return e[0].nodeName&&e[0].nodeName.toLowerCase()===t.toLowerCase()}function c(o){var c=angular.extend({},n,o);c.element||(c.element=p);var g=u(c.element,'body'),m=g?d:c.element,$=g?'window':c.id;if(e[$])return e[$].$$count++,e[$];var h,v,w,y,b,D,k,S,x={},T=x.$trackedElements=[],C=[];return x.init=function(){this.$$count=1,y=s(this.checkPosition,c.debounce),b=l(this.checkPosition,c.throttle),m.on('click',this.checkPositionWithEventLoop),d.on('resize',y),m.on('scroll',b),D=s(this.checkOffsets,c.debounce),h=i.$on('$viewContentLoaded',D),v=i.$on('$includeContentLoaded',D),D(),$&&(e[$]=x)},x.destroy=function(){this.$$count--,this.$$count>0||(m.off('click',this.checkPositionWithEventLoop),d.off('resize',y),m.off('scroll',b),h(),v(),$&&delete e[$])},x.checkPosition=function(){if(C.length){if(S=(g?a.pageYOffset:m.prop('scrollTop'))||0,k=Math.max(a.innerHeight,f.prop('clientHeight')),SC[e+1].offsetTop))return x.$activateElement(C[e])}},x.checkPositionWithEventLoop=function(){setTimeout(x.checkPosition,1)},x.$activateElement=function(e){if(w){var t=x.$getTrackedElement(w);t&&(t.source.removeClass('active'),u(t.source,'li')&&u(t.source.parent().parent(),'li')&&t.source.parent().parent().removeClass('active'))}w=e.target,e.source.addClass('active'),u(e.source,'li')&&u(e.source.parent().parent(),'li')&&e.source.parent().parent().addClass('active')},x.$getTrackedElement=function(e){return T.filter(function(t){return t.target===e})[0]},x.checkOffsets=function(){angular.forEach(T,function(e){var n=t.querySelector(e.target);e.offsetTop=n?r.offset(n).top:null,c.offset&&null!==e.offsetTop&&(e.offsetTop-=1*c.offset)}),C=T.filter(function(e){return null!==e.offsetTop}).sort(function(e,t){return e.offsetTop-t.offsetTop}),y()},x.trackElement=function(e,t){T.push({target:e,source:t})},x.untrackElement=function(e,t){for(var n,a=T.length;a--;)if(T[a].target===e&&T[a].source===t){n=a;break}T=T.splice(n,1)},x.activate=function(e){T[e].addClass('active')},x.init(),x}var d=angular.element(a),f=angular.element(o.prop('documentElement')),p=angular.element(a.document.body);return c}]}).directive('bsScrollspy',['$rootScope','debounce','dimensions','$scrollspy',function(e,t,n,a){return{restrict:'EAC',link:function(e,t,n){var o={scope:e};angular.forEach(['offset','target'],function(e){angular.isDefined(n[e])&&(o[e]=n[e])});var i=a(o);i.trackElement(o.target,t),e.$on('$destroy',function(){i&&(i.untrackElement(o.target,t),i.destroy()),o=null,i=null})}}}]).directive('bsScrollspyList',['$rootScope','debounce','dimensions','$scrollspy',function(e,t,n,a){return{restrict:'A',compile:function(e,t){var n=e[0].querySelectorAll('li > a[href]');angular.forEach(n,function(e){var t=angular.element(e);t.parent().attr('bs-scrollspy','').attr('data-target',t.attr('href'))})}}}]),angular.module('mgcrea.ngStrap.select',['mgcrea.ngStrap.tooltip','mgcrea.ngStrap.helpers.parseOptions']).provider('$select',function(){var e=this.defaults={animation:'am-fade',prefixClass:'select',prefixEvent:'$select',placement:'bottom-left',template:'select/select.tpl.html',trigger:'focus',container:!1,keyboard:!0,html:!1,delay:0,multiple:!1,allNoneButtons:!1,sort:!0,caretHtml:' ',placeholder:'Choose among the following...',allText:'All',noneText:'None',maxLength:3,maxLengthHtml:'selected',iconCheckmark:'glyphicon glyphicon-ok'};this.$get=['$window','$document','$rootScope','$tooltip','$timeout',function(t,n,a,o,i){function r(t,n,a){var r={},s=angular.extend({},e,a);r=o(t,s);var u=r.$scope;u.$matches=[],u.$activeIndex=s.multiple?[]:-1,u.$isMultiple=s.multiple,u.$showAllNoneButtons=s.allNoneButtons&&s.multiple,u.$iconCheckmark=s.iconCheckmark,u.$allText=s.allText,u.$noneText=s.noneText,u.$activate=function(e){u.$$postDigest(function(){r.activate(e)})},u.$select=function(e,t){u.$$postDigest(function(){r.select(e)})},u.$isVisible=function(){return r.$isVisible()},u.$isActive=function(e){return r.$isActive(e)},u.$selectAll=function(){for(var e=0;e=u.$matches.length&&(u.$activeIndex=s.multiple?[]:0)},r.$isVisible=function(){return s.minLength&&n?u.$matches.length&&n.$viewValue.length>=s.minLength:u.$matches.length},r.$isActive=function(e){return s.multiple?-1!==u.$activeIndex.indexOf(e):u.$activeIndex===e},r.$getIndex=function(e){var t=u.$matches.length,n=t;if(t){for(n=t;n--&&u.$matches[n].value!==e;);if(!(0>n))return n}},r.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),l){var t=angular.element(e.target);t.triggerHandler('click')}},r.$onKeyDown=function(e){return/(9|13|38|40)/.test(e.keyCode)?(e.preventDefault(),e.stopPropagation(),s.multiple&&9===e.keyCode?r.hide():s.multiple||13!==e.keyCode&&9!==e.keyCode?void(s.multiple||(38===e.keyCode&&u.$activeIndex>0?u.$activeIndex--:38===e.keyCode&&u.$activeIndex<0?u.$activeIndex=u.$matches.length-1:40===e.keyCode&&u.$activeIndex'),c.after(t)}var d=o(n.bsOptions),f=a(t,r,s),p=d.$match[7].replace(/\|.+/,'').trim();e.$watchCollection(p,function(t,n){d.valuesFn(e,r).then(function(e){f.update(e),r.$render()})}),e.$watch(n.ngModel,function(e,t){f.$updateActiveIndex(),r.$render()},!0),r.$render=function(){var e,n;s.multiple&&angular.isArray(r.$modelValue)?(e=r.$modelValue.map(function(e){return n=f.$getIndex(e),angular.isDefined(n)?f.$scope.$matches[n].label:!1}).filter(angular.isDefined),e=e.length>(s.maxLength||i.maxLength)?e.length+' '+(s.maxLengthHtml||i.maxLengthHtml):e.join(', ')):(n=f.$getIndex(r.$modelValue),e=angular.isDefined(n)?f.$scope.$matches[n].label:!1),t.html((e?e:s.placeholder)+(s.caretHtml?s.caretHtml:i.caretHtml))},s.multiple&&(r.$isEmpty=function(e){return!e||0===e.length}),e.$on('$destroy',function(){f&&f.destroy(),s=null,f=null})}}}]),angular.module('mgcrea.ngStrap.timepicker',['mgcrea.ngStrap.helpers.dateParser','mgcrea.ngStrap.helpers.dateFormatter','mgcrea.ngStrap.tooltip']).provider('$timepicker',function(){var e=this.defaults={animation:'am-fade',prefixClass:'timepicker',placement:'bottom-left',template:'timepicker/timepicker.tpl.html',trigger:'focus',container:!1,keyboard:!0,html:!1,delay:0,useNative:!0,timeType:'date',timeFormat:'shortTime',timezone:null,modelTimeFormat:null,autoclose:!1,minTime:-(1/0),maxTime:+(1/0),length:5,hourStep:1,minuteStep:5,secondStep:5,roundDisplay:!1,iconUp:'glyphicon glyphicon-chevron-up',iconDown:'glyphicon glyphicon-chevron-down',arrowBehavior:'pager'};this.$get=['$window','$document','$rootScope','$sce','$dateFormatter','$tooltip','$timeout',function(t,n,a,o,i,r,s){function l(t,n,a){function o(e){var t=6e4*g.minuteStep;return new Date(Math.floor(e.getTime()/t)*t)}function l(e,n){var a=e+n;if(t[0].createTextRange){var o=t[0].createTextRange();o.collapse(!0),o.moveStart('character',e),o.moveEnd('character',a),o.select()}else t[0].setSelectionRange?t[0].setSelectionRange(e,a):angular.isUndefined(t[0].selectionStart)&&(t[0].selectionStart=e,t[0].selectionEnd=a)}function d(){t[0].focus()}var f=r(t,angular.extend({},e,a)),p=a.scope,g=f.$options,m=f.$scope,$=g.lang,h=function(e,t,n){return i.formatDate(e,t,$,n)},v=0,w=g.roundDisplay?o(new Date):new Date,y=n.$dateValue||w,b={hour:y.getHours(),meridian:y.getHours()<12,minute:y.getMinutes(),second:y.getSeconds(),millisecond:y.getMilliseconds()},D=i.getDatetimeFormat(g.timeFormat,$),k=i.hoursFormat(D),S=i.timeSeparator(D),x=i.minutesFormat(D),T=i.secondsFormat(D),C=i.showSeconds(D),M=i.showAM(D);m.$iconUp=g.iconUp,m.$iconDown=g.iconDown,m.$select=function(e,t){f.select(e,t)},m.$moveIndex=function(e,t){f.$moveIndex(e,t)},m.$switchMeridian=function(e){f.switchMeridian(e)},f.update=function(e){angular.isDate(e)&&!isNaN(e.getTime())?(f.$date=e,angular.extend(b,{hour:e.getHours(),minute:e.getMinutes(),second:e.getSeconds(),millisecond:e.getMilliseconds()}),f.$build()):f.$isBuilt||f.$build()},f.select=function(e,t,a){(!n.$dateValue||isNaN(n.$dateValue.getTime()))&&(n.$dateValue=new Date(1970,0,1)),angular.isDate(e)||(e=new Date(e)),0===t?n.$dateValue.setHours(e.getHours()):1===t?n.$dateValue.setMinutes(e.getMinutes()):2===t&&n.$dateValue.setSeconds(e.getSeconds()),n.$setViewValue(angular.copy(n.$dateValue)),n.$render(),g.autoclose&&!a&&s(function(){f.hide(!0)})},f.switchMeridian=function(e){if(n.$dateValue&&!isNaN(n.$dateValue.getTime())){var t=(e||n.$dateValue).getHours();n.$dateValue.setHours(12>t?t+12:t-12),n.$setViewValue(angular.copy(n.$dateValue)),n.$render()}},f.$build=function(){var e,t,n=m.midIndex=parseInt(g.length/2,10),a=[];for(e=0;e1*g.maxTime},m.$arrowAction=function(e,t){'picker'===g.arrowBehavior?f.$setTimeByStep(e,t):f.$moveIndex(e,t)},f.$setTimeByStep=function(e,t){{var n=new Date(f.$date),a=n.getHours(),o=(h(n,k).length,n.getMinutes()),i=(h(n,x).length,n.getSeconds());h(n,T).length}0===t?n.setHours(a-parseInt(g.hourStep,10)*e):1===t?n.setMinutes(o-parseInt(g.minuteStep,10)*e):2===t&&n.setSeconds(i-parseInt(g.secondStep,10)*e),f.select(n,t,!0)},f.$moveIndex=function(e,t){var n;0===t?(n=new Date(1970,0,1,b.hour+e*g.length,b.minute,b.second),angular.extend(b,{hour:n.getHours()})):1===t?(n=new Date(1970,0,1,b.hour,b.minute+e*g.length*g.minuteStep,b.second),angular.extend(b,{minute:n.getMinutes()})):2===t&&(n=new Date(1970,0,1,b.hour,b.minute,b.second+e*g.length*g.secondStep),angular.extend(b,{second:n.getSeconds()})),f.$build()},f.$onMouseDown=function(e){if('input'!==e.target.nodeName.toLowerCase()&&e.preventDefault(),e.stopPropagation(),c){var t=angular.element(e.target);'button'!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler('click')}},f.$onKeyDown=function(e){if(/(38|37|39|40|13)/.test(e.keyCode)&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),e.stopPropagation(),13===e.keyCode)return f.hide(!0);var t=new Date(f.$date),n=t.getHours(),a=h(t,k).length,o=t.getMinutes(),i=h(t,x).length,r=t.getSeconds(),s=h(t,T).length,u=1,c=/(37|39)/.test(e.keyCode),d=2+1*C+1*M;c&&(37===e.keyCode?v=1>v?d-1:v-1:39===e.keyCode&&(v=d-1>v?v+1:0));var m=[0,a],$=0;38===e.keyCode&&($=-1),40===e.keyCode&&($=1);var w=2===v&&C,y=2===v&&!C||3===v&&C;0===v?(t.setHours(n+$*parseInt(g.hourStep,10)),a=h(t,k).length,m=[0,a]):1===v?(t.setMinutes(o+$*parseInt(g.minuteStep,10)),i=h(t,x).length,m=[a+u,i]):w?(t.setSeconds(r+$*parseInt(g.secondStep,10)),s=h(t,T).length,m=[a+u+i+u,s]):y&&(c||f.switchMeridian(),m=[a+u+i+u+(s+u)*C,2]),f.select(t,v,!0),l(m[0],m[1]),p.$digest()}};var E=f.init;f.init=function(){return u&&g.useNative?(t.prop('type','time'),void t.css('-webkit-appearance','textfield')):(c&&(t.prop('type','text'),t.attr('readonly','true'),t.on('click',d)),void E())};var A=f.destroy;f.destroy=function(){u&&g.useNative&&t.off('click',d),A()};var F=f.show;f.show=function(){F(),s(function(){f.$element.on(c?'touchstart':'mousedown',f.$onMouseDown),g.keyboard&&t.on('keydown',f.$onKeyDown)},0,!1)};var V=f.hide;return f.hide=function(e){f.$isShown&&(f.$element.off(c?'touchstart':'mousedown',f.$onMouseDown),g.keyboard&&t.off('keydown',f.$onKeyDown),V(e))},f}var u=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),c='createTouch'in t.document&&u;return e.lang||(e.lang=i.getDefaultLocale()),l.defaults=e,l}]}).directive('bsTimepicker',['$window','$parse','$q','$dateFormatter','$dateParser','$timepicker',function(e,t,n,a,o,i){{var r=i.defaults,s=/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent);e.requestAnimationFrame||e.setTimeout}return{restrict:'EAC',require:'ngModel',link:function(e,t,n,l){function u(e){if(angular.isDate(e)){var t=isNaN(d.minTime)||new Date(e.getTime()).setFullYear(1970,0,1)>=d.minTime,n=isNaN(d.maxTime)||new Date(e.getTime()).setFullYear(1970,0,1)<=d.maxTime,a=t&&n;l.$setValidity('date',a),l.$setValidity('min',t),l.$setValidity('max',n),a&&(l.$dateValue=e)}}function c(){return!l.$dateValue||isNaN(l.$dateValue.getTime())?'':m(l.$dateValue,d.timeFormat)}var d={scope:e,controller:l};angular.forEach(['placement','container','delay','trigger','keyboard','html','animation','template','autoclose','timeType','timeFormat','timezone','modelTimeFormat','useNative','hourStep','minuteStep','secondStep','length','arrowBehavior','iconUp','iconDown','roundDisplay','id','prefixClass','prefixEvent'],function(e){angular.isDefined(n[e])&&(d[e]=n[e])});var f=/^(false|0|)$/i;angular.forEach(['html','container','autoclose','useNative','roundDisplay'],function(e){angular.isDefined(n[e])&&f.test(n[e])&&(d[e]=!1)}),n.bsShow&&e.$watch(n.bsShow,function(e,t){p&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(timepicker),?/i)),e===!0?p.show():p.hide())}),s&&(d.useNative||r.useNative)&&(d.timeFormat='HH:mm');var p=i(t,l,d);d=p.$options;var g=d.lang,m=function(e,t,n){return a.formatDate(e,t,g,n)},$=o({format:d.timeFormat,lang:g});angular.forEach(['minTime','maxTime'],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){p.$options[e]=$.getTimeForAttribute(e,t),!isNaN(p.$options[e])&&p.$build(),u(l.$dateValue)})}),e.$watch(n.ngModel,function(e,t){p.update(l.$dateValue)},!0),l.$parsers.unshift(function(e){var t;if(!e)return l.$setValidity('date',!0),null;var n=angular.isDate(e)?e:$.parse(e,l.$dateValue);return!n||isNaN(n.getTime())?void l.$setValidity('date',!1):(u(n),'string'===d.timeType?(t=$.timezoneOffsetAdjust(n,d.timezone,!0),m(t,d.modelTimeFormat||d.timeFormat)):(t=$.timezoneOffsetAdjust(l.$dateValue,d.timezone,!0),'number'===d.timeType?t.getTime():'unix'===d.timeType?t.getTime()/1e3:'iso'===d.timeType?t.toISOString():new Date(t)))}),l.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:'string'===d.timeType?$.parse(e,null,d.modelTimeFormat):new Date('unix'===d.timeType?1e3*e:e),l.$dateValue=$.timezoneOffsetAdjust(t,d.timezone),c()}),l.$render=function(){t.val(c())},e.$on('$destroy',function(){p&&p.destroy(),d=null,p=null})}}}]),angular.module('mgcrea.ngStrap.tab',[]).provider('$tab',function(){var e=this.defaults={animation:'am-fade',template:'tab/tab.tpl.html',navClass:'nav-tabs',activeClass:'active'},t=this.controller=function(t,n,a){var o=this;o.$options=angular.copy(e),angular.forEach(['animation','navClass','activeClass'],function(e){angular.isDefined(a[e])&&(o.$options[e]=a[e])}),t.$navClass=o.$options.navClass,t.$activeClass=o.$options.activeClass,o.$panes=t.$panes=[],o.$activePaneChangeListeners=o.$viewChangeListeners=[],o.$push=function(e){o.$panes.push(e)},o.$remove=function(e){var t=o.$panes.indexOf(e),n=o.$panes.$active;o.$panes.splice(t,1),n>t?n--:t===n&&n===o.$panes.length&&n--,o.$setActive(n)},o.$panes.$active=0,o.$setActive=t.$setActive=function(e){o.$panes.$active=e,o.$activePaneChangeListeners.forEach(function(e){e()})}};this.$get=function(){var n={};return n.defaults=e,n.controller=t,n}}).directive('bsTabs',['$window','$animate','$tab','$parse',function(e,t,n,a){var o=n.defaults;return{require:['?ngModel','bsTabs'],transclude:!0,scope:!0,controller:['$scope','$element','$attrs',n.controller],templateUrl:function(e,t){return t.template||o.template},link:function(e,t,n,o){var i=o[0],r=o[1];if(i&&(r.$activePaneChangeListeners.push(function(){i.$setViewValue(r.$panes.$active)}),i.$formatters.push(function(e){return r.$setActive(1*e),e})),n.bsActivePane){var s=a(n.bsActivePane);r.$activePaneChangeListeners.push(function(){s.assign(e,r.$panes.$active)}),e.$watch(n.bsActivePane,function(e,t){r.$setActive(1*e)},!0)}}}}]).directive('bsPane',['$window','$animate','$sce',function(e,t,n){return{require:['^?ngModel','^bsTabs'],scope:!0,link:function(e,a,o,i){function r(){var n=s.$panes.indexOf(e),o=s.$panes.$active;t[n===o?'addClass':'removeClass'](a,s.$options.activeClass)}var s=(i[0],i[1]);a.addClass('tab-pane'),o.$observe('title',function(t,a){e.title=n.trustAsHtml(t)}),s.$options.animation&&a.addClass(s.$options.animation),o.$observe('disabled',function(t,n){e.disabled=e.$eval(t)}),s.$push(e),e.$on('$destroy',function(){s.$remove(e)}),s.$activePaneChangeListeners.push(function(){r()}),r()}}}]),angular.module('mgcrea.ngStrap.tooltip',['mgcrea.ngStrap.helpers.dimensions']).provider('$tooltip',function(){var e=this.defaults={animation:'am-fade',customClass:'',prefixClass:'tooltip',prefixEvent:'tooltip',container:!1,target:!1,placement:'top',template:'tooltip/tooltip.tpl.html',contentTemplate:!1,trigger:'hover focus',keyboard:!1,html:!1,show:!1,title:'',type:'',delay:0,autoClose:!1,bsEnabled:!0,viewport:{selector:'body',padding:0}};this.$get=['$window','$rootScope','$compile','$q','$templateCache','$http','$animate','$sce','dimensions','$$rAF','$timeout',function(n,a,o,i,r,s,l,u,c,d,f){function p(i,r){function s(){N.$emit(H.prefixEvent+'.show',I)}function p(){if(N.$emit(H.prefixEvent+'.hide',I),z===B){if(W&&'focus'===H.trigger)return i[0].blur();O()}}function b(){var e=H.trigger.split(' ');angular.forEach(e,function(e){'click'===e?i.on('click',I.toggle):'manual'!==e&&(i.on('hover'===e?'mouseenter':'focus',I.enter),i.on('hover'===e?'mouseleave':'blur',I.leave),'button'===P&&'hover'!==e&&i.on(v?'touchstart':'mousedown',I.$onFocusElementMouseDown))})}function D(){for(var e=H.trigger.split(' '),t=e.length;t--;){var n=e[t];'click'===n?i.off('click',I.toggle):'manual'!==n&&(i.off('hover'===n?'mouseenter':'focus',I.enter),i.off('hover'===n?'mouseleave':'blur',I.leave),'button'===P&&'hover'!==n&&i.off(v?'touchstart':'mousedown',I.$onFocusElementMouseDown))}}function k(){'focus'!==H.trigger?z.on('keyup',I.$onKeyUp):i.on('keyup',I.$onFocusKeyUp)}function S(){'focus'!==H.trigger?z.off('keyup',I.$onKeyUp):i.off('keyup',I.$onFocusKeyUp)}function x(){f(function(){z.on('click',C),y.on('click',I.hide),_=!0},0,!1)}function T(){_&&(z.off('click',C),y.off('click',I.hide),_=!1)}function C(e){e.stopPropagation()}function M(e){e=e||H.target||i;var a=e[0],o='BODY'===a.tagName,r=a.getBoundingClientRect(),s={};for(var l in r)s[l]=r[l];null===s.width&&(s=angular.extend({},s,{width:r.right-r.left,height:r.bottom-r.top}));var u=o?{top:0,left:0}:c.offset(a),d={scroll:o?t.documentElement.scrollTop||t.body.scrollTop:e.prop('scrollTop')||0},f=o?{width:t.documentElement.clientWidth,height:n.innerHeight}:null;return angular.extend({},s,d,f,u)}function E(e,t,n,a){var o,i=e.split('-');switch(i[0]){case'right':o={top:t.top+t.height/2-a/2,left:t.left+t.width};break;case'bottom':o={top:t.top+t.height,left:t.left+t.width/2-n/2};break;case'left':o={top:t.top+t.height/2-a/2,left:t.left-n};break;default:o={top:t.top-a,left:t.left+t.width/2-n/2}}if(!i[1])return o;if('top'===i[0]||'bottom'===i[0])switch(i[1]){case'left':o.left=t.left;break;case'right':o.left=t.left+t.width-n}else if('left'===i[0]||'right'===i[0])switch(i[1]){case'top': -o.top=t.top-a;break;case'bottom':o.top=t.top+t.height}return o}function A(e,t){var n=z[0],a=n.offsetWidth,o=n.offsetHeight,i=parseInt(c.css(n,'margin-top'),10),r=parseInt(c.css(n,'margin-left'),10);isNaN(i)&&(i=0),isNaN(r)&&(r=0),e.top=e.top+i,e.left=e.left+r,c.setOffset(n,angular.extend({using:function(e){z.css({top:Math.round(e.top)+'px',left:Math.round(e.left)+'px',right:''})}},e),0);var s=n.offsetWidth,l=n.offsetHeight;if('top'===t&&l!==o&&(e.top=e.top+o-l),!/top-left|top-right|bottom-left|bottom-right/.test(t)){var u=F(t,e,s,l);if(u.left?e.left+=u.left:e.top+=u.top,c.setOffset(n,e),/top|right|bottom|left/.test(t)){var d=/top|bottom/.test(t),f=d?2*u.left-a+s:2*u.top-o+l,p=d?'offsetWidth':'offsetHeight';V(f,n[p],d)}}}function F(e,t,n,a){var o={top:0,left:0},i=H.viewport&&m(H.viewport.selector||H.viewport);if(!i)return o;var r=H.viewport&&H.viewport.padding||0,s=M(i);if(/right|left/.test(e)){var l=t.top-r-s.scroll,u=t.top+r-s.scroll+a;ls.top+s.height&&(o.top=s.top+s.height-u)}else{var c=t.left-r,d=t.left+r+n;cs.width&&(o.left=s.left+s.width-d)}return o}function V(e,t,n){var a=m('.tooltip-arrow, .arrow',z[0]);a.css(n?'left':'top',50*(1-e/t)+'%').css(n?'top':'left','')}function O(){clearTimeout(R),I.$isShown&&null!==z&&(H.autoClose&&T(),H.keyboard&&S()),j&&(j.$destroy(),j=null),z&&(z.remove(),z=I.$element=null)}var I={},P=i[0].nodeName.toLowerCase(),H=I.$options=angular.extend({},e,r);I.$promise=$(H.template);var N=I.$scope=H.scope&&H.scope.$new()||a.$new();if(H.delay&&angular.isString(H.delay)){var L=H.delay.split(',').map(parseFloat);H.delay=L.length>1?{show:L[0],hide:L[1]}:L[0]}I.$id=H.id||i.attr('id')||'',H.title&&(N.title=u.trustAsHtml(H.title)),N.$setEnabled=function(e){N.$$postDigest(function(){I.setEnabled(e)})},N.$hide=function(){N.$$postDigest(function(){I.hide()})},N.$show=function(){N.$$postDigest(function(){I.show()})},N.$toggle=function(){N.$$postDigest(function(){I.toggle()})},I.$isShown=N.$isShown=!1;var R,Y;H.contentTemplate&&(I.$promise=I.$promise.then(function(e){var t=angular.element(e);return $(H.contentTemplate).then(function(e){var n=m('[ng-bind="content"]',t[0]);return n.length||(n=m('[ng-bind="title"]',t[0])),n.removeAttr('ng-bind').html(e),t[0].outerHTML})}));var q,z,K,U,j;I.$promise.then(function(e){angular.isObject(e)&&(e=e.data),H.html&&(e=e.replace(w,'ng-bind-html="')),e=h.apply(e),K=e,q=o(e),I.init()}),I.init=function(){H.delay&&angular.isNumber(H.delay)&&(H.delay={show:H.delay,hide:H.delay}),'self'===H.container?U=i:angular.isElement(H.container)?U=H.container:H.container&&(U=m(H.container)),b(),H.target&&(H.target=angular.isElement(H.target)?H.target:m(H.target)),H.show&&N.$$postDigest(function(){'focus'===H.trigger?i[0].focus():I.show()})},I.destroy=function(){D(),O(),N.$destroy()},I.enter=function(){return clearTimeout(R),Y='in',H.delay&&H.delay.show?void(R=setTimeout(function(){'in'===Y&&I.show()},H.delay.show)):I.show()},I.show=function(){if(H.bsEnabled&&!I.$isShown){N.$emit(H.prefixEvent+'.show.before',I);var e,t;H.container?(e=U,t=U[0].lastChild?angular.element(U[0].lastChild):null):(e=null,t=i),z&&O(),j=I.$scope.$new(),z=I.$element=q(j,function(e,t){}),z.css({top:'-9999px',left:'-9999px',right:'auto',display:'block',visibility:'hidden'}),H.animation&&z.addClass(H.animation),H.type&&z.addClass(H.prefixClass+'-'+H.type),H.customClass&&z.addClass(H.customClass),t?t.after(z):e.prepend(z),I.$isShown=N.$isShown=!0,g(N),I.$applyPlacement();var n=l.enter(z,e,t,s);n&&n.then&&n.then(s),g(N),d(function(){z&&z.css({visibility:'visible'})}),H.keyboard&&('focus'!==H.trigger&&I.focus(),k()),H.autoClose&&x()}},I.leave=function(){return clearTimeout(R),Y='out',H.delay&&H.delay.hide?void(R=setTimeout(function(){'out'===Y&&I.hide()},H.delay.hide)):I.hide()};var W,B;I.hide=function(e){if(I.$isShown){N.$emit(H.prefixEvent+'.hide.before',I),W=e,B=z;var t=l.leave(z,p);t&&t.then&&t.then(p),I.$isShown=N.$isShown=!1,g(N),H.keyboard&&null!==z&&S(),H.autoClose&&null!==z&&T()}},I.toggle=function(){I.$isShown?I.leave():I.enter()},I.focus=function(){z[0].focus()},I.setEnabled=function(e){H.bsEnabled=e},I.setViewport=function(e){H.viewport=e},I.$applyPlacement=function(){if(z){var t=H.placement,n=/\s?auto?\s?/i,a=n.test(t);a&&(t=t.replace(n,'')||e.placement),z.addClass(H.placement);var o=M(),r=z.prop('offsetWidth'),s=z.prop('offsetHeight');if(a){var l=t,u=H.container?m(H.container):i.parent(),c=M(u);l.indexOf('bottom')>=0&&o.bottom+s>c.bottom?t=l.replace('bottom','top'):l.indexOf('top')>=0&&o.top-sc.width?t='right'===l?'left':t.replace('left','right'):('left'===l||'bottom-right'===l||'top-right'===l)&&o.left-r=e.length&&(u.$activeIndex=s.autoSelect?0:-1),/^(bottom|bottom-left|bottom-right)$/.test(s.placement)||o(r.$applyPlacement)},r.activate=function(e){u.$activeIndex=e},r.select=function(e){if(-1!==e){var t=u.$matches[e].value;n.$setViewValue(t),n.$render(),u.$resetMatches(),l&&l.$digest(),u.$emit(s.prefixEvent+'.select',t,e,r)}},r.$isVisible=function(){return s.minLength&&n?u.$matches.length&&angular.isString(n.$viewValue)&&n.$viewValue.length>=s.minLength:!!u.$matches.length},r.$getIndex=function(e){var t=u.$matches.length,n=t;if(t){for(n=t;n--&&u.$matches[n].value!==e;);if(!(0>n))return n}},r.$onMouseDown=function(e){e.preventDefault(),e.stopPropagation()},r.$onKeyDown=function(e){/(38|40|13)/.test(e.keyCode)&&(!r.$isVisible()||13===e.keyCode&&-1===u.$activeIndex||(e.preventDefault(),e.stopPropagation()),13===e.keyCode&&u.$matches.length?r.select(u.$activeIndex):38===e.keyCode&&u.$activeIndex>0?u.$activeIndex--:40===e.keyCode&&u.$activeIndex0)return void s.$setViewValue(s.$viewValue.substring(0,s.$viewValue.length-1));e.length>d&&(e=e.slice(0,d));var n=m.$isVisible();n&&m.update(e),(1!==e.length||e[0].value!==t)&&(!n&&m.update(e),s.$render())})}),s.$formatters.push(function(e){var t=g.displayValue(e);return t===n?'':t}),s.$render=function(){if(s.$isEmpty(s.$viewValue))return t.val('');var e=m.$getIndex(s.$modelValue),n=angular.isDefined(e)?m.$scope.$matches[e].label:s.$viewValue;n=angular.isObject(n)?g.displayValue(n):n;var a=n?n.toString().replace(/<(?:.|\n)*?>/gm,''):'';t.val(l.trimValue===!1?a:a.trim())},e.$on('$destroy',function(){m&&m.destroy(),l=null,m=null})}}}])}(window,document); +!function(e,t,n){'use strict';angular.module('mgcrea.ngStrap',['mgcrea.ngStrap.modal','mgcrea.ngStrap.aside','mgcrea.ngStrap.alert','mgcrea.ngStrap.button','mgcrea.ngStrap.select','mgcrea.ngStrap.datepicker','mgcrea.ngStrap.timepicker','mgcrea.ngStrap.navbar','mgcrea.ngStrap.tooltip','mgcrea.ngStrap.popover','mgcrea.ngStrap.dropdown','mgcrea.ngStrap.typeahead','mgcrea.ngStrap.scrollspy','mgcrea.ngStrap.affix','mgcrea.ngStrap.tab','mgcrea.ngStrap.collapse']),angular.module('mgcrea.ngStrap.affix',['mgcrea.ngStrap.helpers.dimensions','mgcrea.ngStrap.helpers.debounce']).provider('$affix',function(){var e=this.defaults={offsetTop:'auto',inlineStyles:!0};this.$get=['$window','debounce','dimensions',function(t,n,a){function o(o,s){function l(e,t,n){var a=u(),o=c();return v>=a?'top':null!==e&&a+e<=t.top?'middle':null!==w&&t.top+n+$>=o-w?'bottom':'middle'}function u(){return p[0]===t?t.pageYOffset:p[0].scrollTop}function c(){return p[0]===t?t.document.body.scrollHeight:p[0].scrollHeight}var d={},f=angular.extend({},e,s),p=f.target,g='affix affix-top affix-bottom',m=!1,$=0,h=0,v=0,w=0,y=null,b=null,D=o.parent();if(f.offsetParent)if(f.offsetParent.match(/^\d+$/))for(var k=0;k<1*f.offsetParent-1;k++)D=D.parent();else D=angular.element(f.offsetParent);return d.init=function(){this.$parseOffsets(),h=a.offset(o[0]).top+$,m=!o[0].style.width,p.on('scroll',this.checkPosition),p.on('click',this.checkPositionWithEventLoop),r.on('resize',this.$debouncedOnResize),this.checkPosition(),this.checkPositionWithEventLoop()},d.destroy=function(){p.off('scroll',this.checkPosition),p.off('click',this.checkPositionWithEventLoop),r.off('resize',this.$debouncedOnResize)},d.checkPositionWithEventLoop=function(){setTimeout(d.checkPosition,1)},d.checkPosition=function(){var e=u(),t=a.offset(o[0]),n=a.height(o[0]),r=l(b,t,n);y!==r&&(y=r,o.removeClass(g).addClass('affix'+('middle'!==r?'-'+r:'')),'top'===r?(b=null,m&&o.css('width',''),f.inlineStyles&&(o.css('position',f.offsetParent?'':'relative'),o.css('top',''))):'bottom'===r?(b=f.offsetUnpin?-(1*f.offsetUnpin):t.top-e,m&&o.css('width',''),f.inlineStyles&&(o.css('position',f.offsetParent?'':'relative'),o.css('top',f.offsetParent?'':i[0].offsetHeight-w-n-h+'px'))):(b=null,m&&o.css('width',o[0].offsetWidth+'px'),f.inlineStyles&&(o.css('position','fixed'),o.css('top',$+'px'))))},d.$onResize=function(){d.$parseOffsets(),d.checkPosition()},d.$debouncedOnResize=n(d.$onResize,50),d.$parseOffsets=function(){var e=o.css('position');f.inlineStyles&&o.css('position',f.offsetParent?'':'relative'),f.offsetTop&&('auto'===f.offsetTop&&(f.offsetTop='+0'),f.offsetTop.match(/^[-+]\d+$/)?($=1*-f.offsetTop,v=f.offsetParent?a.offset(D[0]).top+1*f.offsetTop:a.offset(o[0]).top-a.css(o[0],'marginTop',!0)+1*f.offsetTop):v=1*f.offsetTop),f.offsetBottom&&(w=f.offsetParent&&f.offsetBottom.match(/^[-+]\d+$/)?c()-(a.offset(D[0]).top+a.height(D[0]))+1*f.offsetBottom+1:1*f.offsetBottom),f.inlineStyles&&o.css('position',e)},d.init(),d}var i=angular.element(t.document.body),r=angular.element(t);return o}]}).directive('bsAffix',['$affix','$window',function(e,t){return{restrict:'EAC',require:'^?bsAffixTarget',link:function(n,a,o,i){var r={scope:n,target:i?i.$element:angular.element(t)};angular.forEach(['offsetTop','offsetBottom','offsetParent','offsetUnpin','inlineStyles'],function(e){if(angular.isDefined(o[e])){var t=o[e];/true/i.test(t)&&(t=!0),/false/i.test(t)&&(t=!1),r[e]=t}});var s=e(a,r);n.$on('$destroy',function(){s&&s.destroy(),r=null,s=null})}}}]).directive('bsAffixTarget',function(){return{controller:['$element',function(e){this.$element=e}]}}),angular.module('mgcrea.ngStrap.button',[]).provider('$button',function(){var e=this.defaults={activeClass:'active',toggleEvent:'click'};this.$get=function(){return{defaults:e}}}).directive('bsCheckboxGroup',function(){return{restrict:'A',require:'ngModel',compile:function(e,t){e.attr('data-toggle','buttons'),e.removeAttr('ng-model');var n=e[0].querySelectorAll('input[type="checkbox"]');angular.forEach(n,function(e){var n=angular.element(e);n.attr('bs-checkbox',''),n.attr('ng-model',t.ngModel+'.'+n.attr('value'))})}}}).directive('bsCheckbox',['$button','$$rAF',function(e,t){var n=e.defaults,a=/^(true|false|\d+)$/;return{restrict:'A',require:'ngModel',link:function(e,o,i,r){var s=n,l='INPUT'===o[0].nodeName,u=l?o.parent():o,c=angular.isDefined(i.trueValue)?i.trueValue:!0;a.test(i.trueValue)&&(c=e.$eval(i.trueValue));var d=angular.isDefined(i.falseValue)?i.falseValue:!1;a.test(i.falseValue)&&(d=e.$eval(i.falseValue));var f='boolean'!=typeof c||'boolean'!=typeof d;f&&(r.$parsers.push(function(e){return e?c:d}),r.$formatters.push(function(e){return angular.equals(e,c)}),e.$watch(i.ngModel,function(e,t){r.$render()})),r.$render=function(){var e=angular.equals(r.$modelValue,c);t(function(){l&&(o[0].checked=e),u.toggleClass(s.activeClass,e)})},o.bind(s.toggleEvent,function(){e.$apply(function(){l||r.$setViewValue(!u.hasClass('active')),f||r.$render()})})}}}]).directive('bsRadioGroup',function(){return{restrict:'A',require:'ngModel',compile:function(e,t){e.attr('data-toggle','buttons'),e.removeAttr('ng-model');var n=e[0].querySelectorAll('input[type="radio"]');angular.forEach(n,function(e){angular.element(e).attr('bs-radio',''),angular.element(e).attr('ng-model',t.ngModel)})}}}).directive('bsRadio',['$button','$$rAF',function(e,t){var n=e.defaults,a=/^(true|false|\d+)$/;return{restrict:'A',require:'ngModel',link:function(e,o,i,r){var s,l=n,u='INPUT'===o[0].nodeName,c=u?o.parent():o;i.$observe('value',function(t){s=a.test(t)?e.$eval(t):t,r.$render()}),r.$render=function(){var e=angular.equals(r.$modelValue,s);t(function(){u&&(o[0].checked=e),c.toggleClass(l.activeClass,e)})},o.bind(l.toggleEvent,function(){e.$apply(function(){r.$setViewValue(s),r.$render()})})}}}]),angular.module('mgcrea.ngStrap.alert',['mgcrea.ngStrap.modal']).provider('$alert',function(){var e=this.defaults={animation:'am-fade',prefixClass:'alert',prefixEvent:'alert',placement:null,template:'alert/alert.tpl.html',container:!1,element:null,backdrop:!1,keyboard:!0,show:!0,duration:!1,type:!1,dismissable:!0};this.$get=['$modal','$timeout',function(t,n){function a(a){var o={},i=angular.extend({},e,a);o=t(i),o.$scope.dismissable=!!i.dismissable,i.type&&(o.$scope.type=i.type);var r=o.show;return i.duration&&(o.show=function(){r(),n(function(){o.hide()},1e3*i.duration)}),o}return a}]}).directive('bsAlert',['$window','$sce','$alert',function(e,t,n){e.requestAnimationFrame||e.setTimeout;return{restrict:'EAC',scope:!0,link:function(e,a,o,i){var r={scope:e,element:a,show:!1};angular.forEach(['template','placement','keyboard','html','container','animation','duration','dismissable'],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var s=/^(false|0|)$/i;angular.forEach(['keyboard','html','container','dismissable'],function(e){angular.isDefined(o[e])&&s.test(o[e])&&(r[e]=!1)}),e.hasOwnProperty('title')||(e.title=''),angular.forEach(['title','content','type'],function(n){o[n]&&o.$observe(n,function(a,o){e[n]=t.trustAsHtml(a)})}),o.bsAlert&&e.$watch(o.bsAlert,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var l=n(r);a.on(o.trigger||'click',l.toggle),e.$on('$destroy',function(){l&&l.destroy(),r=null,l=null})}}}]),angular.module('mgcrea.ngStrap.aside',['mgcrea.ngStrap.modal']).provider('$aside',function(){var e=this.defaults={animation:'am-fade-and-slide-right',prefixClass:'aside',prefixEvent:'aside',placement:'right',template:'aside/aside.tpl.html',contentTemplate:!1,container:!1,element:null,backdrop:!0,keyboard:!0,html:!1,show:!0};this.$get=['$modal',function(t){function n(n){var a={},o=angular.extend({},e,n);return a=t(o)}return n}]}).directive('bsAside',['$window','$sce','$aside',function(e,t,n){e.requestAnimationFrame||e.setTimeout;return{restrict:'EAC',scope:!0,link:function(e,a,o,i){var r={scope:e,element:a,show:!1};angular.forEach(['template','contentTemplate','placement','backdrop','keyboard','html','container','animation'],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var s=/^(false|0|)$/i;angular.forEach(['backdrop','keyboard','html','container'],function(e){angular.isDefined(o[e])&&s.test(o[e])&&(r[e]=!1)}),angular.forEach(['title','content'],function(n){o[n]&&o.$observe(n,function(a,o){e[n]=t.trustAsHtml(a)})}),o.bsAside&&e.$watch(o.bsAside,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var l=n(r);a.on(o.trigger||'click',l.toggle),e.$on('$destroy',function(){l&&l.destroy(),r=null,l=null})}}}]),angular.module('mgcrea.ngStrap.collapse',[]).provider('$collapse',function(){var e=this.defaults={animation:'am-collapse',disallowToggle:!1,activeClass:'in',startCollapsed:!1,allowMultiple:!1},t=this.controller=function(t,n,a){function o(e){for(var t=l.$targets.$active,n=0;nt;t++)angular.forEach(g.rows[t],u.$setDisabledEl)},u.select=function(e,t){angular.isDate(n.$dateValue)||(n.$dateValue=new Date(e)),!g.$mode||t?(n.$setViewValue(angular.copy(e)),n.$render(),p.autoclose&&!t&&l(function(){u.hide(!0)})):(angular.extend($,{year:e.getFullYear(),month:e.getMonth(),date:e.getDate()}),u.setMode(g.$mode-1),u.$build())},u.setMode=function(e){g.$mode=e,h=u.$views[g.$mode],u.$build()},u.$build=function(e){e===!0&&h.built||(e!==!1||h.built)&&h.build.call(h)},u.$updateSelected=function(){for(var e=0,t=g.rows.length;t>e;e++)angular.forEach(g.rows[e],o)},u.$isSelected=function(e){return h.isSelected(e)},u.$setDisabledEl=function(e){e.disabled=h.isDisabled(e.date)},u.$selectPane=function(e){var t=h.steps,n=new Date(Date.UTC($.year+(t.year||0)*e,$.month+(t.month||0)*e,1));angular.extend($,{year:n.getUTCFullYear(),month:n.getUTCMonth(),date:n.getUTCDate()}),u.$build()},u.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),d){var t=angular.element(e.target);'button'!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler('click')}},u.$onKeyDown=function(e){if(/(38|37|39|40|13)/.test(e.keyCode)&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),e.stopPropagation(),13===e.keyCode)return g.$mode?g.$apply(function(){u.setMode(g.$mode-1)}):u.hide(!0);h.onKeyDown(e),f.$digest()}};var v=u.init;u.init=function(){return c&&p.useNative?(t.prop('type','date'),void t.css('-webkit-appearance','textfield')):(d&&(t.prop('type','text'),t.attr('readonly','true'),t.on('click',i)),void v())};var w=u.destroy;u.destroy=function(){c&&p.useNative&&t.off('click',i),w()};var y=u.show;u.show=function(){y(),l(function(){u.$isShown&&(u.$element.on(d?'touchstart':'mousedown',u.$onMouseDown),p.keyboard&&t.on('keydown',u.$onKeyDown))},0,!1)};var b=u.hide;return u.hide=function(e){u.$isShown&&(u.$element.off(d?'touchstart':'mousedown',u.$onMouseDown),p.keyboard&&t.off('keydown',u.$onKeyDown),b(e))},u}var c=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),d='createTouch'in t.document&&c;return e.lang||(e.lang=i.getDefaultLocale()),u.defaults=e,u}]}).directive('bsDatepicker',['$window','$parse','$q','$dateFormatter','$dateParser','$datepicker',function(e,t,n,a,o,i){var r=(i.defaults,/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent));return{restrict:'EAC',require:'ngModel',link:function(e,t,n,s){function l(e){return e&&e.length?e:null}function u(e){if(angular.isDate(e)){var t=isNaN(p.$options.minDate)||e.getTime()>=p.$options.minDate,n=isNaN(p.$options.maxDate)||e.getTime()<=p.$options.maxDate,a=t&&n;s.$setValidity('date',a),s.$setValidity('min',t),s.$setValidity('max',n),a&&(s.$dateValue=e)}}function c(){return!s.$dateValue||isNaN(s.$dateValue.getTime())?'':m(s.$dateValue,d.dateFormat)}var d={scope:e,controller:s};angular.forEach(['placement','container','delay','trigger','html','animation','template','autoclose','dateType','dateFormat','timezone','modelDateFormat','dayFormat','strictFormat','startWeek','startDate','useNative','lang','startView','minView','iconLeft','iconRight','daysOfWeekDisabled','id','prefixClass','prefixEvent'],function(e){angular.isDefined(n[e])&&(d[e]=n[e])});var f=/^(false|0|)$/i;angular.forEach(['html','container','autoclose','useNative'],function(e){angular.isDefined(n[e])&&f.test(n[e])&&(d[e]=!1)}),n.bsShow&&e.$watch(n.bsShow,function(e,t){p&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(datepicker),?/i)),e===!0?p.show():p.hide())});var p=i(t,s,d);d=p.$options,r&&d.useNative&&(d.dateFormat='yyyy-MM-dd');var g=d.lang,m=function(e,t){return a.formatDate(e,t,g)},$=o({format:d.dateFormat,lang:g,strict:d.strictFormat});angular.forEach(['minDate','maxDate'],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){p.$options[e]=$.getDateForAttribute(e,t),!isNaN(p.$options[e])&&p.$build(!1),u(s.$dateValue)})}),e.$watch(n.ngModel,function(e,t){p.update(s.$dateValue)},!0),angular.isDefined(n.disabledDates)&&e.$watch(n.disabledDates,function(e,t){e=l(e),t=l(t),e&&p.updateDisabledDates(e)}),s.$parsers.unshift(function(e){var t;if(!e)return s.$setValidity('date',!0),null;var n=$.parse(e,s.$dateValue);return!n||isNaN(n.getTime())?void s.$setValidity('date',!1):(u(n),'string'===d.dateType?(t=$.timezoneOffsetAdjust(n,d.timezone,!0),m(t,d.modelDateFormat||d.dateFormat)):(t=$.timezoneOffsetAdjust(s.$dateValue,d.timezone,!0),'number'===d.dateType?t.getTime():'unix'===d.dateType?t.getTime()/1e3:'iso'===d.dateType?t.toISOString():new Date(t)))}),s.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:'string'===d.dateType?$.parse(e,null,d.modelDateFormat):new Date('unix'===d.dateType?1e3*e:e),s.$dateValue=$.timezoneOffsetAdjust(t,d.timezone),c()}),s.$render=function(){t.val(c())},e.$on('$destroy',function(){p&&p.destroy(),d=null,p=null})}}}]).provider('datepickerViews',function(){function e(e,t){for(var n=[];e.length>0;)n.push(e.splice(0,t));return n}function t(e,t){return(e%t+t)%t}this.defaults={dayFormat:'dd',daySplit:7};this.$get=['$dateFormatter','$dateParser','$sce',function(n,a,o){return function(i){var r=i.$scope,s=i.$options,l=s.lang,u=function(e,t){return n.formatDate(e,t,l)},c=a({format:s.dateFormat,lang:l,strict:s.strictFormat}),d=n.weekdaysShort(l),f=d.slice(s.startWeek).concat(d.slice(0,s.startWeek)),p=o.trustAsHtml(''+f.join('')+''),g=i.$date||(s.startDate?c.getDateForAttribute('startDate',s.startDate):new Date),m={year:g.getFullYear(),month:g.getMonth(),date:g.getDate()},$=[{format:s.dayFormat,split:7,steps:{month:1},update:function(e,t){!this.built||t||e.getFullYear()!==m.year||e.getMonth()!==m.month?(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build()):(e.getDate()!==m.date||1===e.getDate())&&(m.date=i.$date.getDate(),i.$updateSelected())},build:function(){var n=new Date(m.year,m.month,1),a=n.getTimezoneOffset(),o=new Date(+n-864e5*t(n.getDay()-s.startWeek,7)),l=o.getTimezoneOffset(),d=c.timezoneOffsetAdjust(new Date,s.timezone).toDateString();l!==a&&(o=new Date(+o+6e4*(l-a)));for(var f,g=[],$=0;42>$;$++)f=c.daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth(),o.getDate()+$)),g.push({date:f,isToday:f.toDateString()===d,label:u(f,this.format),selected:i.$date&&this.isSelected(f),muted:f.getMonth()!==m.month,disabled:this.isDisabled(f)});r.title=u(n,s.monthTitleFormat),r.showLabels=!0,r.labels=p,r.rows=e(g,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()&&e.getMonth()===i.$date.getMonth()&&e.getDate()===i.$date.getDate()},isDisabled:function(e){var t=e.getTime();if(ts.maxDate)return!0;if(-1!==s.daysOfWeekDisabled.indexOf(e.getDay()))return!0;if(s.disabledDateRanges)for(var n=0;n=s.disabledDateRanges[n].start&&t<=s.disabledDateRanges[n].end)return!0;return!1},onKeyDown:function(e){if(i.$date){var t,n=i.$date.getTime();37===e.keyCode?t=new Date(n-864e5):38===e.keyCode?t=new Date(n-6048e5):39===e.keyCode?t=new Date(n+864e5):40===e.keyCode&&(t=new Date(n+6048e5)),this.isDisabled(t)||i.select(t,!0)}}},{name:'month',format:s.monthFormat,split:4,steps:{year:1},update:function(e,t){this.built&&e.getFullYear()===m.year?e.getMonth()!==m.month&&(angular.extend(m,{month:i.$date.getMonth(),date:i.$date.getDate()}),i.$updateSelected()):(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build())},build:function(){for(var t,n=(new Date(m.year,0,1),[]),a=0;12>a;a++)t=new Date(m.year,a,1),n.push({date:t,label:u(t,this.format),selected:i.$isSelected(t),disabled:this.isDisabled(t)});r.title=u(t,s.yearTitleFormat),r.showLabels=!1,r.rows=e(n,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()&&e.getMonth()===i.$date.getMonth()},isDisabled:function(e){var t=+new Date(e.getFullYear(),e.getMonth()+1,0);return ts.maxDate},onKeyDown:function(e){if(i.$date){var t=i.$date.getMonth(),n=new Date(i.$date);37===e.keyCode?n.setMonth(t-1):38===e.keyCode?n.setMonth(t-4):39===e.keyCode?n.setMonth(t+1):40===e.keyCode&&n.setMonth(t+4),this.isDisabled(n)||i.select(n,!0)}}},{name:'year',format:s.yearFormat,split:4,steps:{year:12},update:function(e,t){!this.built||t||parseInt(e.getFullYear()/20,10)!==parseInt(m.year/20,10)?(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$build()):e.getFullYear()!==m.year&&(angular.extend(m,{year:i.$date.getFullYear(),month:i.$date.getMonth(),date:i.$date.getDate()}),i.$updateSelected())},build:function(){for(var t,n=m.year-m.year%(3*this.split),a=[],o=0;12>o;o++)t=new Date(n+o,0,1),a.push({date:t,label:u(t,this.format),selected:i.$isSelected(t),disabled:this.isDisabled(t)});r.title=a[0].label+'-'+a[a.length-1].label,r.showLabels=!1,r.rows=e(a,this.split),this.built=!0},isSelected:function(e){return i.$date&&e.getFullYear()===i.$date.getFullYear()},isDisabled:function(e){var t=+new Date(e.getFullYear()+1,0,0);return ts.maxDate},onKeyDown:function(e){if(i.$date){var t=i.$date.getFullYear(),n=new Date(i.$date);37===e.keyCode?n.setYear(t-1):38===e.keyCode?n.setYear(t-4):39===e.keyCode?n.setYear(t+1):40===e.keyCode&&n.setYear(t+4),this.isDisabled(n)||i.select(n,!0)}}}];return{views:s.minView?Array.prototype.slice.call($,s.minView):$,viewDate:m}}}]}),angular.module('mgcrea.ngStrap.dropdown',['mgcrea.ngStrap.tooltip']).provider('$dropdown',function(){var e=this.defaults={animation:'am-fade',prefixClass:'dropdown',prefixEvent:'dropdown',placement:'bottom-left',template:'dropdown/dropdown.tpl.html',trigger:'click',container:!1,keyboard:!0,html:!1,delay:0};this.$get=['$window','$rootScope','$tooltip','$timeout',function(t,n,a,o){function i(t,i){function l(e){return e.target!==t[0]?e.target!==t[0]&&u.hide():void 0}{var u={},c=angular.extend({},e,i);u.$scope=c.scope&&c.scope.$new()||n.$new()}u=a(t,c);var d=t.parent();u.$onKeyDown=function(e){if(/(38|40)/.test(e.keyCode)){e.preventDefault(),e.stopPropagation();var t=angular.element(u.$element[0].querySelectorAll('li:not(.divider) a'));if(t.length){var n;angular.forEach(t,function(e,t){s&&s.call(e,':focus')&&(n=t)}),38===e.keyCode&&n>0?n--:40===e.keyCode&&no;o++)if(e[o].toLowerCase()===a)return o;return-1}t.prototype.setMilliseconds=function(e){this.milliseconds=e},t.prototype.setSeconds=function(e){this.seconds=e},t.prototype.setMinutes=function(e){this.minutes=e},t.prototype.setHours=function(e){this.hours=e},t.prototype.getHours=function(){return this.hours},t.prototype.setDate=function(e){this.day=e},t.prototype.setMonth=function(e){this.month=e},t.prototype.setFullYear=function(e){this.year=e},t.prototype.fromDate=function(e){return this.year=e.getFullYear(),this.month=e.getMonth(),this.day=e.getDate(),this.hours=e.getHours(),this.minutes=e.getMinutes(),this.seconds=e.getSeconds(),this.milliseconds=e.getMilliseconds(),this},t.prototype.toDate=function(){return new Date(this.year,this.month,this.day,this.hours,this.minutes,this.seconds,this.milliseconds)};var i=t.prototype,r=this.defaults={format:'shortDate',strict:!1};this.$get=['$locale','dateFilter',function(e,s){var l=function(l){function u(e){var t,n=Object.keys(h),a=[],o=[],i=e;for(t=0;t1){var r=i.search(n[t]);e=e.split(n[t]).join(''),h[n[t]]&&(a[r]=h[n[t]])}return angular.forEach(a,function(e){e&&o.push(e)}),o}function c(e){return e.replace(/\//g,'[\\/]').replace('/-/g','[-]').replace(/\./g,'[.]').replace(/\\s/g,'[\\s]')}function d(e){var t,n=Object.keys($),a=e;for(t=0;t12?e.getHours()+2:0),e):null},m.timezoneOffsetAdjust=function(e,t,n){return e?(t&&'UTC'===t&&(e=new Date(e.getTime()),e.setMinutes(e.getMinutes()+(n?-1:1)*e.getTimezoneOffset())),e):null},m.init(),m};return l}]}]),angular.module('mgcrea.ngStrap.helpers.debounce',[]).factory('debounce',['$timeout',function(e){return function(t,n,a){var o=null;return function(){var i=this,r=arguments,s=a&&!o;return o&&e.cancel(o),o=e(function(){o=null,a||t.apply(i,r)},n,!1),s&&t.apply(i,r),o}}}]).factory('throttle',['$timeout',function(e){return function(t,n,a){var o=null;return a||(a={}),function(){var i=this,r=arguments;o||(a.leading!==!1&&t.apply(i,r),o=e(function(){o=null,a.trailing!==!1&&t.apply(i,r)},n,!1))}}}]),angular.module('mgcrea.ngStrap.helpers.dimensions',[]).factory('dimensions',['$document','$window',function(t,n){var a=(angular.element,{}),o=a.nodeName=function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()};a.css=function(t,n,a){var o;return o=t.currentStyle?t.currentStyle[n]:e.getComputedStyle?e.getComputedStyle(t)[n]:t.style[n],a===!0?parseFloat(o)||0:o},a.offset=function(t){var n=t.getBoundingClientRect(),a=t.ownerDocument;return{width:n.width||t.offsetWidth,height:n.height||t.offsetHeight,top:n.top+(e.pageYOffset||a.documentElement.scrollTop)-(a.documentElement.clientTop||0),left:n.left+(e.pageXOffset||a.documentElement.scrollLeft)-(a.documentElement.clientLeft||0)}},a.setOffset=function(e,t,n){var o,i,r,s,l,u,c,d=a.css(e,'position'),f=angular.element(e),p={};'static'===d&&(e.style.position='relative'),l=a.offset(e),r=a.css(e,'top'),u=a.css(e,'left'),c=('absolute'===d||'fixed'===d)&&(r+u).indexOf('auto')>-1,c?(o=a.position(e),s=o.top,i=o.left):(s=parseFloat(r)||0,i=parseFloat(u)||0),angular.isFunction(t)&&(t=t.call(e,n,l)), +null!==t.top&&(p.top=t.top-l.top+s),null!==t.left&&(p.left=t.left-l.left+i),'using'in t?t.using.call(f,p):f.css({top:p.top+'px',left:p.left+'px'})},a.position=function(e){var t,n,r={top:0,left:0};return'fixed'===a.css(e,'position')?n=e.getBoundingClientRect():(t=i(e),n=a.offset(e),o(t,'html')||(r=a.offset(t)),r.top+=a.css(t,'borderTopWidth',!0),r.left+=a.css(t,'borderLeftWidth',!0)),{width:e.offsetWidth,height:e.offsetHeight,top:n.top-r.top-a.css(e,'marginTop',!0),left:n.left-r.left-a.css(e,'marginLeft',!0)}};var i=function(e){var t=e.ownerDocument,n=e.offsetParent||t;if(o(n,'#document'))return t.documentElement;for(;n&&!o(n,'html')&&'static'===a.css(n,'position');)n=n.offsetParent;return n||t.documentElement};return a.height=function(e,t){var n=e.offsetHeight;return t?n+=a.css(e,'marginTop',!0)+a.css(e,'marginBottom',!0):n-=a.css(e,'paddingTop',!0)+a.css(e,'paddingBottom',!0)+a.css(e,'borderTopWidth',!0)+a.css(e,'borderBottomWidth',!0),n},a.width=function(e,t){var n=e.offsetWidth;return t?n+=a.css(e,'marginLeft',!0)+a.css(e,'marginRight',!0):n-=a.css(e,'paddingLeft',!0)+a.css(e,'paddingRight',!0)+a.css(e,'borderLeftWidth',!0)+a.css(e,'borderRightWidth',!0),n},a}]),angular.module('mgcrea.ngStrap.helpers.parseOptions',[]).provider('$parseOptions',function(){var e=this.defaults={regexp:/^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/};this.$get=['$parse','$q',function(t,n){function a(a,o){function i(e,t){return e.map(function(e,n){var a,o,i={};return i[c]=e,a=u(t,i),o=p(t,i),{label:a,value:o,index:n}})}var r={},s=angular.extend({},e,o);r.$values=[];var l,u,c,d,f,p,g;return r.init=function(){r.$match=l=a.match(s.regexp),u=t(l[2]||l[1]),c=l[4]||l[6],d=l[5],f=t(l[3]||''),p=t(l[2]?l[1]:c),g=t(l[7])},r.valuesFn=function(e,t){return n.when(g(e,t)).then(function(t){return r.$values=t?i(t,e):{},r.$values})},r.displayValue=function(e){var t={};return t[c]=e,u(t)},r.init(),r}return a}]}),angular.version.minor<3&&angular.version.dot<14&&angular.module('ng').factory('$$rAF',['$window','$timeout',function(e,t){var n=e.requestAnimationFrame||e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame,a=e.cancelAnimationFrame||e.webkitCancelAnimationFrame||e.mozCancelAnimationFrame||e.webkitCancelRequestAnimationFrame,o=!!n,i=o?function(e){var t=n(e);return function(){a(t)}}:function(e){var n=t(e,16.66,!1);return function(){t.cancel(n)}};return i.supported=o,i}]),angular.module('mgcrea.ngStrap.modal',['mgcrea.ngStrap.helpers.dimensions']).provider('$modal',function(){var e=this.defaults={animation:'am-fade',backdropAnimation:'am-fade',prefixClass:'modal',prefixEvent:'modal',placement:'top',template:'modal/modal.tpl.html',contentTemplate:!1,container:!1,element:null,backdrop:!0,keyboard:!0,html:!1,show:!0};this.$get=['$window','$rootScope','$compile','$q','$templateCache','$http','$animate','$timeout','$sce','dimensions',function(n,a,o,i,r,s,l,u,c,d){function f(t){function n(){f.$emit(d.prefixEvent+'.show',u)}function i(){f.$emit(d.prefixEvent+'.hide',u),w.removeClass(d.prefixClass+'-open'),d.animation&&w.removeClass(d.prefixClass+'-with-'+d.animation)}function r(e){e.target===e.currentTarget&&('static'===d.backdrop?u.focus():u.hide())}function s(e){e.preventDefault()}var u={},d=u.$options=angular.extend({},e,t);u.$promise=m(d.template);var f=u.$scope=d.scope&&d.scope.$new()||a.$new();d.element||d.container||(d.container='body'),u.$id=d.id||d.element&&d.element.attr('id')||'',$(['title','content'],function(e){d[e]&&(f[e]=c.trustAsHtml(d[e]))}),f.$hide=function(){f.$$postDigest(function(){u.hide()})},f.$show=function(){f.$$postDigest(function(){u.show()})},f.$toggle=function(){f.$$postDigest(function(){u.toggle()})},u.$isShown=f.$isShown=!1,d.contentTemplate&&(u.$promise=u.$promise.then(function(e){var n=angular.element(e);return m(d.contentTemplate).then(function(e){var a=g('[ng-bind="content"]',n[0]).removeAttr('ng-bind').html(e);return t.template||a.next().remove(),n[0].outerHTML})}));var b,D,k=angular.element('
');return k.css({position:'fixed',top:'0px',left:'0px',bottom:'0px',right:'0px','z-index':1038}),u.$promise.then(function(e){angular.isObject(e)&&(e=e.data),d.html&&(e=e.replace(y,'ng-bind-html="')),e=h.apply(e),b=o(e),u.init()}),u.init=function(){d.show&&f.$$postDigest(function(){u.show()})},u.destroy=function(){D&&(D.remove(),D=null),k&&(k.remove(),k=null),f.$destroy()},u.show=function(){if(!u.$isShown){var e,t;if(angular.isElement(d.container)?(e=d.container,t=d.container[0].lastChild?angular.element(d.container[0].lastChild):null):d.container?(e=g(d.container),t=e[0]&&e[0].lastChild?angular.element(e[0].lastChild):null):(e=null,t=d.element),D=u.$element=b(f,function(e,t){}),!f.$emit(d.prefixEvent+'.show.before',u).defaultPrevented){D.css({display:'block'}).addClass(d.placement),d.animation&&(d.backdrop&&k.addClass(d.backdropAnimation),D.addClass(d.animation)),d.backdrop&&l.enter(k,w,null);var a=l.enter(D,e,t,n);a&&a.then&&a.then(n),u.$isShown=f.$isShown=!0,p(f);var o=D[0];v(function(){o.focus()}),w.addClass(d.prefixClass+'-open'),d.animation&&w.addClass(d.prefixClass+'-with-'+d.animation),d.backdrop&&(D.on('click',r),k.on('click',r),k.on('wheel',s)),d.keyboard&&D.on('keyup',u.$onKeyUp)}}},u.hide=function(){if(u.$isShown&&!f.$emit(d.prefixEvent+'.hide.before',u).defaultPrevented){var e=l.leave(D,i);e&&e.then&&e.then(i),d.backdrop&&l.leave(k),u.$isShown=f.$isShown=!1,p(f),d.backdrop&&(D.off('click',r),k.off('click',r),k.off('wheel',s)),d.keyboard&&D.off('keyup',u.$onKeyUp)}},u.toggle=function(){u.$isShown?u.hide():u.show()},u.focus=function(){D[0].focus()},u.$onKeyUp=function(e){27===e.which&&u.$isShown&&(u.hide(),e.stopPropagation())},u}function p(e){e.$$phase||e.$root&&e.$root.$$phase||e.$digest()}function g(e,n){return angular.element((n||t).querySelectorAll(e))}function m(e){return b[e]?b[e]:b[e]=s.get(e,{cache:r}).then(function(e){return e.data})}var $=angular.forEach,h=String.prototype.trim,v=n.requestAnimationFrame||n.setTimeout,w=angular.element(n.document.body),y=/ng-bind="/gi,b={};return f}]}).directive('bsModal',['$window','$sce','$modal',function(e,t,n){return{restrict:'EAC',scope:!0,link:function(e,a,o,i){var r={scope:e,element:a,show:!1};angular.forEach(['template','contentTemplate','placement','backdrop','keyboard','html','container','animation','id','prefixEvent','prefixClass'],function(e){angular.isDefined(o[e])&&(r[e]=o[e])});var s=/^(false|0|)$/i;angular.forEach(['backdrop','keyboard','html','container'],function(e){angular.isDefined(o[e])&&s.test(o[e])&&(r[e]=!1)}),angular.forEach(['title','content'],function(n){o[n]&&o.$observe(n,function(a,o){e[n]=t.trustAsHtml(a)})}),o.bsModal&&e.$watch(o.bsModal,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t},!0);var l=n(r);a.on(o.trigger||'click',l.toggle),e.$on('$destroy',function(){l&&l.destroy(),r=null,l=null})}}}]),angular.module('mgcrea.ngStrap.navbar',[]).provider('$navbar',function(){var e=this.defaults={activeClass:'active',routeAttr:'data-match-route',strict:!1};this.$get=function(){return{defaults:e}}}).directive('bsNavbar',['$window','$location','$navbar',function(e,t,n){var a=n.defaults;return{restrict:'A',link:function(e,n,o,i){var r=angular.copy(a);angular.forEach(Object.keys(a),function(e){angular.isDefined(o[e])&&(r[e]=o[e])}),e.$watch(function(){return t.path()},function(e,t){var a=n[0].querySelectorAll('li['+r.routeAttr+']');angular.forEach(a,function(t){var n=angular.element(t),a=n.attr(r.routeAttr).replace('/','\\/');r.strict&&(a='^'+a+'$');var o=new RegExp(a,'i');o.test(e)?n.addClass(r.activeClass):n.removeClass(r.activeClass)})})}}}]),angular.module('mgcrea.ngStrap.popover',['mgcrea.ngStrap.tooltip']).provider('$popover',function(){var e=this.defaults={animation:'am-fade',customClass:'',container:!1,target:!1,placement:'right',template:'popover/popover.tpl.html',contentTemplate:!1,trigger:'click',keyboard:!0,html:!1,title:'',content:'',delay:0,autoClose:!1};this.$get=['$tooltip',function(t){function n(n,a){var o=angular.extend({},e,a),i=t(n,o);return o.content&&(i.$scope.content=o.content),i}return n}]}).directive('bsPopover',['$window','$sce','$popover',function(e,t,n){var a=e.requestAnimationFrame||e.setTimeout;return{restrict:'EAC',scope:!0,link:function(e,o,i){var r={scope:e};angular.forEach(['template','contentTemplate','placement','container','delay','trigger','html','animation','customClass','autoClose','id','prefixClass','prefixEvent'],function(e){angular.isDefined(i[e])&&(r[e]=i[e])});var s=/^(false|0|)$/i;angular.forEach(['html','container','autoClose'],function(e){angular.isDefined(i[e])&&s.test(i[e])&&(r[e]=!1)});var l=o.attr('data-target');angular.isDefined(l)&&(r.target=s.test(l)?!1:l),angular.forEach(['title','content'],function(n){i[n]&&i.$observe(n,function(o,i){e[n]=t.trustAsHtml(o),angular.isDefined(i)&&a(function(){u&&u.$applyPlacement()})})}),i.bsPopover&&e.$watch(i.bsPopover,function(t,n){angular.isObject(t)?angular.extend(e,t):e.content=t,angular.isDefined(n)&&a(function(){u&&u.$applyPlacement()})},!0),i.bsShow&&e.$watch(i.bsShow,function(e,t){u&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(popover),?/i)),e===!0?u.show():u.hide())}),i.viewport&&e.$watch(i.viewport,function(e){u&&angular.isDefined(e)&&u.setViewport(e)});var u=n(o,r);e.$on('$destroy',function(){u&&u.destroy(),r=null,u=null})}}}]),angular.module('mgcrea.ngStrap.scrollspy',['mgcrea.ngStrap.helpers.debounce','mgcrea.ngStrap.helpers.dimensions']).provider('$scrollspy',function(){var e=this.$$spies={},n=this.defaults={debounce:150,throttle:100,offset:100};this.$get=['$window','$document','$rootScope','dimensions','debounce','throttle',function(a,o,i,r,s,l){function u(e,t){return e[0].nodeName&&e[0].nodeName.toLowerCase()===t.toLowerCase()}function c(o){var c=angular.extend({},n,o);c.element||(c.element=p);var g=u(c.element,'body'),m=g?d:c.element,$=g?'window':c.id;if(e[$])return e[$].$$count++,e[$];var h,v,w,y,b,D,k,S,x={},T=x.$trackedElements=[],C=[];return x.init=function(){this.$$count=1,y=s(this.checkPosition,c.debounce),b=l(this.checkPosition,c.throttle),m.on('click',this.checkPositionWithEventLoop),d.on('resize',y),m.on('scroll',b),D=s(this.checkOffsets,c.debounce),h=i.$on('$viewContentLoaded',D),v=i.$on('$includeContentLoaded',D),D(),$&&(e[$]=x)},x.destroy=function(){this.$$count--,this.$$count>0||(m.off('click',this.checkPositionWithEventLoop),d.off('resize',y),m.off('scroll',b),h(),v(),$&&delete e[$])},x.checkPosition=function(){if(C.length){if(S=(g?a.pageYOffset:m.prop('scrollTop'))||0,k=Math.max(a.innerHeight,f.prop('clientHeight')),SC[e+1].offsetTop))return x.$activateElement(C[e])}},x.checkPositionWithEventLoop=function(){setTimeout(x.checkPosition,1)},x.$activateElement=function(e){if(w){var t=x.$getTrackedElement(w);t&&(t.source.removeClass('active'),u(t.source,'li')&&u(t.source.parent().parent(),'li')&&t.source.parent().parent().removeClass('active'))}w=e.target,e.source.addClass('active'),u(e.source,'li')&&u(e.source.parent().parent(),'li')&&e.source.parent().parent().addClass('active')},x.$getTrackedElement=function(e){return T.filter(function(t){return t.target===e})[0]},x.checkOffsets=function(){angular.forEach(T,function(e){var n=t.querySelector(e.target);e.offsetTop=n?r.offset(n).top:null,c.offset&&null!==e.offsetTop&&(e.offsetTop-=1*c.offset)}),C=T.filter(function(e){return null!==e.offsetTop}).sort(function(e,t){return e.offsetTop-t.offsetTop}),y()},x.trackElement=function(e,t){T.push({target:e,source:t})},x.untrackElement=function(e,t){for(var n,a=T.length;a--;)if(T[a].target===e&&T[a].source===t){n=a;break}T=T.splice(n,1)},x.activate=function(e){T[e].addClass('active')},x.init(),x}var d=angular.element(a),f=angular.element(o.prop('documentElement')),p=angular.element(a.document.body);return c}]}).directive('bsScrollspy',['$rootScope','debounce','dimensions','$scrollspy',function(e,t,n,a){return{restrict:'EAC',link:function(e,t,n){var o={scope:e};angular.forEach(['offset','target'],function(e){angular.isDefined(n[e])&&(o[e]=n[e])});var i=a(o);i.trackElement(o.target,t),e.$on('$destroy',function(){i&&(i.untrackElement(o.target,t),i.destroy()),o=null,i=null})}}}]).directive('bsScrollspyList',['$rootScope','debounce','dimensions','$scrollspy',function(e,t,n,a){return{restrict:'A',compile:function(e,t){var n=e[0].querySelectorAll('li > a[href]');angular.forEach(n,function(e){var t=angular.element(e);t.parent().attr('bs-scrollspy','').attr('data-target',t.attr('href'))})}}}]),angular.module('mgcrea.ngStrap.select',['mgcrea.ngStrap.tooltip','mgcrea.ngStrap.helpers.parseOptions']).provider('$select',function(){var e=this.defaults={animation:'am-fade',prefixClass:'select',prefixEvent:'$select',placement:'bottom-left',template:'select/select.tpl.html',trigger:'focus',container:!1,keyboard:!0,html:!1,delay:0,multiple:!1,allNoneButtons:!1,sort:!0,caretHtml:' ',placeholder:'Choose among the following...',allText:'All',noneText:'None',maxLength:3,maxLengthHtml:'selected',iconCheckmark:'glyphicon glyphicon-ok'};this.$get=['$window','$document','$rootScope','$tooltip','$timeout',function(t,n,a,o,i){function r(t,n,a){var r={},s=angular.extend({},e,a);r=o(t,s);var u=r.$scope;u.$matches=[],u.$activeIndex=s.multiple?[]:-1,u.$isMultiple=s.multiple,u.$showAllNoneButtons=s.allNoneButtons&&s.multiple,u.$iconCheckmark=s.iconCheckmark,u.$allText=s.allText,u.$noneText=s.noneText,u.$activate=function(e){u.$$postDigest(function(){r.activate(e)})},u.$select=function(e,t){u.$$postDigest(function(){r.select(e)})},u.$isVisible=function(){return r.$isVisible()},u.$isActive=function(e){return r.$isActive(e)},u.$selectAll=function(){for(var e=0;e=u.$matches.length&&(u.$activeIndex=s.multiple?[]:0)},r.$isVisible=function(){return s.minLength&&n?u.$matches.length&&n.$viewValue.length>=s.minLength:u.$matches.length},r.$isActive=function(e){return s.multiple?-1!==u.$activeIndex.indexOf(e):u.$activeIndex===e},r.$getIndex=function(e){var t=u.$matches.length,n=t;if(t){for(n=t;n--&&u.$matches[n].value!==e;);if(!(0>n))return n}},r.$onMouseDown=function(e){if(e.preventDefault(),e.stopPropagation(),l){var t=angular.element(e.target);t.triggerHandler('click')}},r.$onKeyDown=function(e){return/(9|13|38|40)/.test(e.keyCode)?(e.preventDefault(),e.stopPropagation(),s.multiple&&9===e.keyCode?r.hide():s.multiple||13!==e.keyCode&&9!==e.keyCode?void(s.multiple||(38===e.keyCode&&u.$activeIndex>0?u.$activeIndex--:38===e.keyCode&&u.$activeIndex<0?u.$activeIndex=u.$matches.length-1:40===e.keyCode&&u.$activeIndex'),c.after(t)}var d=o(n.bsOptions),f=a(t,r,s),p=d.$match[7].replace(/\|.+/,'').trim();e.$watchCollection(p,function(t,n){d.valuesFn(e,r).then(function(e){f.update(e),r.$render()})}),e.$watch(n.ngModel,function(e,t){f.$updateActiveIndex(),r.$render()},!0),r.$render=function(){var e,n;s.multiple&&angular.isArray(r.$modelValue)?(e=r.$modelValue.map(function(e){return n=f.$getIndex(e),angular.isDefined(n)?f.$scope.$matches[n].label:!1}).filter(angular.isDefined),e=e.length>(s.maxLength||i.maxLength)?e.length+' '+(s.maxLengthHtml||i.maxLengthHtml):e.join(', ')):(n=f.$getIndex(r.$modelValue),e=angular.isDefined(n)?f.$scope.$matches[n].label:!1),t.html((e?e:s.placeholder)+(s.caretHtml?s.caretHtml:i.caretHtml))},s.multiple&&(r.$isEmpty=function(e){return!e||0===e.length}),e.$on('$destroy',function(){f&&f.destroy(),s=null,f=null})}}}]),angular.module('mgcrea.ngStrap.tab',[]).provider('$tab',function(){var e=this.defaults={animation:'am-fade',template:'tab/tab.tpl.html',navClass:'nav-tabs',activeClass:'active'},t=this.controller=function(t,n,a){var o=this;o.$options=angular.copy(e),angular.forEach(['animation','navClass','activeClass'],function(e){angular.isDefined(a[e])&&(o.$options[e]=a[e])}),t.$navClass=o.$options.navClass,t.$activeClass=o.$options.activeClass,o.$panes=t.$panes=[],o.$activePaneChangeListeners=o.$viewChangeListeners=[],o.$push=function(e){angular.isUndefined(o.$panes.$active)&&t.$setActive(e.name||0),o.$panes.push(e)},o.$remove=function(e){var t,n=o.$panes.indexOf(e),a=o.$panes.$active;t=angular.isString(a)?o.$panes.map(function(e){return e.name}).indexOf(a):o.$panes.$active,o.$panes.splice(n,1),t>n?t--:n===t&&t===o.$panes.length&&t--,t>=0&&tt?t+12:t-12),n.$setViewValue(angular.copy(n.$dateValue)),n.$render()}},f.$build=function(){var e,t,n=m.midIndex=parseInt(g.length/2,10),a=[];for(e=0;e1*g.maxTime},m.$arrowAction=function(e,t){'picker'===g.arrowBehavior?f.$setTimeByStep(e,t):f.$moveIndex(e,t)},f.$setTimeByStep=function(e,t){{var n=new Date(f.$date),a=n.getHours(),o=(h(n,k).length,n.getMinutes()),i=(h(n,x).length,n.getSeconds());h(n,T).length}0===t?n.setHours(a-parseInt(g.hourStep,10)*e):1===t?n.setMinutes(o-parseInt(g.minuteStep,10)*e):2===t&&n.setSeconds(i-parseInt(g.secondStep,10)*e),f.select(n,t,!0)},f.$moveIndex=function(e,t){var n;0===t?(n=new Date(1970,0,1,b.hour+e*g.length,b.minute,b.second),angular.extend(b,{hour:n.getHours()})):1===t?(n=new Date(1970,0,1,b.hour,b.minute+e*g.length*g.minuteStep,b.second),angular.extend(b,{minute:n.getMinutes()})):2===t&&(n=new Date(1970,0,1,b.hour,b.minute,b.second+e*g.length*g.secondStep),angular.extend(b,{second:n.getSeconds()})),f.$build()},f.$onMouseDown=function(e){if('input'!==e.target.nodeName.toLowerCase()&&e.preventDefault(),e.stopPropagation(),c){var t=angular.element(e.target);'button'!==t[0].nodeName.toLowerCase()&&(t=t.parent()),t.triggerHandler('click')}},f.$onKeyDown=function(e){if(/(38|37|39|40|13)/.test(e.keyCode)&&!e.shiftKey&&!e.altKey){if(e.preventDefault(),e.stopPropagation(),13===e.keyCode)return f.hide(!0);var t=new Date(f.$date),n=t.getHours(),a=h(t,k).length,o=t.getMinutes(),i=h(t,x).length,r=t.getSeconds(),s=h(t,T).length,u=1,c=/(37|39)/.test(e.keyCode),d=2+1*C+1*M;c&&(37===e.keyCode?v=1>v?d-1:v-1:39===e.keyCode&&(v=d-1>v?v+1:0));var m=[0,a],$=0;38===e.keyCode&&($=-1),40===e.keyCode&&($=1);var w=2===v&&C,y=2===v&&!C||3===v&&C;0===v?(t.setHours(n+$*parseInt(g.hourStep,10)),a=h(t,k).length,m=[0,a]):1===v?(t.setMinutes(o+$*parseInt(g.minuteStep,10)),i=h(t,x).length,m=[a+u,i]):w?(t.setSeconds(r+$*parseInt(g.secondStep,10)),s=h(t,T).length,m=[a+u+i+u,s]):y&&(c||f.switchMeridian(),m=[a+u+i+u+(s+u)*C,2]),f.select(t,v,!0),l(m[0],m[1]),p.$digest()}};var E=f.init;f.init=function(){return u&&g.useNative?(t.prop('type','time'),void t.css('-webkit-appearance','textfield')):(c&&(t.prop('type','text'),t.attr('readonly','true'),t.on('click',d)),void E())};var A=f.destroy;f.destroy=function(){u&&g.useNative&&t.off('click',d),A()};var F=f.show;f.show=function(){F(),s(function(){f.$element.on(c?'touchstart':'mousedown',f.$onMouseDown),g.keyboard&&t.on('keydown',f.$onKeyDown)},0,!1)};var V=f.hide;return f.hide=function(e){f.$isShown&&(f.$element.off(c?'touchstart':'mousedown',f.$onMouseDown),g.keyboard&&t.off('keydown',f.$onKeyDown),V(e))},f}var u=(angular.element(t.document.body),/(ip(a|o)d|iphone|android)/gi.test(t.navigator.userAgent)),c='createTouch'in t.document&&u;return e.lang||(e.lang=i.getDefaultLocale()),l.defaults=e,l}]}).directive('bsTimepicker',['$window','$parse','$q','$dateFormatter','$dateParser','$timepicker',function(e,t,n,a,o,i){{var r=i.defaults,s=/(ip(a|o)d|iphone|android)/gi.test(e.navigator.userAgent);e.requestAnimationFrame||e.setTimeout}return{restrict:'EAC',require:'ngModel',link:function(e,t,n,l){function u(e){if(angular.isDate(e)){var t=isNaN(d.minTime)||new Date(e.getTime()).setFullYear(1970,0,1)>=d.minTime,n=isNaN(d.maxTime)||new Date(e.getTime()).setFullYear(1970,0,1)<=d.maxTime,a=t&&n;l.$setValidity('date',a),l.$setValidity('min',t),l.$setValidity('max',n),a&&(l.$dateValue=e)}}function c(){return!l.$dateValue||isNaN(l.$dateValue.getTime())?'':m(l.$dateValue,d.timeFormat)}var d={scope:e,controller:l};angular.forEach(['placement','container','delay','trigger','keyboard','html','animation','template','autoclose','timeType','timeFormat','timezone','modelTimeFormat','useNative','hourStep','minuteStep','secondStep','length','arrowBehavior','iconUp','iconDown','roundDisplay','id','prefixClass','prefixEvent'],function(e){angular.isDefined(n[e])&&(d[e]=n[e])});var f=/^(false|0|)$/i;angular.forEach(['html','container','autoclose','useNative','roundDisplay'],function(e){angular.isDefined(n[e])&&f.test(n[e])&&(d[e]=!1)}),n.bsShow&&e.$watch(n.bsShow,function(e,t){p&&angular.isDefined(e)&&(angular.isString(e)&&(e=!!e.match(/true|,?(timepicker),?/i)),e===!0?p.show():p.hide())}),s&&(d.useNative||r.useNative)&&(d.timeFormat='HH:mm');var p=i(t,l,d);d=p.$options;var g=d.lang,m=function(e,t,n){return a.formatDate(e,t,g,n)},$=o({format:d.timeFormat,lang:g});angular.forEach(['minTime','maxTime'],function(e){angular.isDefined(n[e])&&n.$observe(e,function(t){p.$options[e]=$.getTimeForAttribute(e,t),!isNaN(p.$options[e])&&p.$build(),u(l.$dateValue)})}),e.$watch(n.ngModel,function(e,t){p.update(l.$dateValue)},!0),l.$parsers.unshift(function(e){var t;if(!e)return l.$setValidity('date',!0),null;var n=angular.isDate(e)?e:$.parse(e,l.$dateValue);return!n||isNaN(n.getTime())?void l.$setValidity('date',!1):(u(n),'string'===d.timeType?(t=$.timezoneOffsetAdjust(n,d.timezone,!0),m(t,d.modelTimeFormat||d.timeFormat)):(t=$.timezoneOffsetAdjust(l.$dateValue,d.timezone,!0),'number'===d.timeType?t.getTime():'unix'===d.timeType?t.getTime()/1e3:'iso'===d.timeType?t.toISOString():new Date(t)))}),l.$formatters.push(function(e){var t;return t=angular.isUndefined(e)||null===e?0/0:angular.isDate(e)?e:'string'===d.timeType?$.parse(e,null,d.modelTimeFormat):new Date('unix'===d.timeType?1e3*e:e),l.$dateValue=$.timezoneOffsetAdjust(t,d.timezone),c()}),l.$render=function(){t.val(c())},e.$on('$destroy',function(){p&&p.destroy(),d=null,p=null})}}}]),angular.module('mgcrea.ngStrap.tooltip',['mgcrea.ngStrap.helpers.dimensions']).provider('$tooltip',function(){var e=this.defaults={animation:'am-fade',customClass:'',prefixClass:'tooltip',prefixEvent:'tooltip',container:!1,target:!1,placement:'top',template:'tooltip/tooltip.tpl.html',contentTemplate:!1,trigger:'hover focus',keyboard:!1,html:!1,show:!1,title:'',type:'',delay:0,autoClose:!1,bsEnabled:!0,viewport:{selector:'body',padding:0}};this.$get=['$window','$rootScope','$compile','$q','$templateCache','$http','$animate','$sce','dimensions','$$rAF','$timeout',function(n,a,o,i,r,s,l,u,c,d,f){function p(i,r){function s(){N.$emit(H.prefixEvent+'.show',I)}function p(){if(N.$emit(H.prefixEvent+'.hide',I),z===B){if(W&&'focus'===H.trigger)return i[0].blur();O()}}function b(){var e=H.trigger.split(' ');angular.forEach(e,function(e){'click'===e?i.on('click',I.toggle):'manual'!==e&&(i.on('hover'===e?'mouseenter':'focus',I.enter),i.on('hover'===e?'mouseleave':'blur',I.leave),'button'===P&&'hover'!==e&&i.on(v?'touchstart':'mousedown',I.$onFocusElementMouseDown))})}function D(){for(var e=H.trigger.split(' '),t=e.length;t--;){var n=e[t];'click'===n?i.off('click',I.toggle):'manual'!==n&&(i.off('hover'===n?'mouseenter':'focus',I.enter),i.off('hover'===n?'mouseleave':'blur',I.leave),'button'===P&&'hover'!==n&&i.off(v?'touchstart':'mousedown',I.$onFocusElementMouseDown))}}function k(){'focus'!==H.trigger?z.on('keyup',I.$onKeyUp):i.on('keyup',I.$onFocusKeyUp)}function S(){'focus'!==H.trigger?z.off('keyup',I.$onKeyUp):i.off('keyup',I.$onFocusKeyUp)}function x(){f(function(){z.on('click',C),y.on('click',I.hide),_=!0},0,!1)}function T(){_&&(z.off('click',C),y.off('click',I.hide),_=!1)}function C(e){e.stopPropagation()}function M(e){e=e||H.target||i;var a=e[0],o='BODY'===a.tagName,r=a.getBoundingClientRect(),s={};for(var l in r)s[l]=r[l];null===s.width&&(s=angular.extend({},s,{width:r.right-r.left,height:r.bottom-r.top}));var u=o?{top:0,left:0}:c.offset(a),d={scroll:o?t.documentElement.scrollTop||t.body.scrollTop:e.prop('scrollTop')||0},f=o?{width:t.documentElement.clientWidth,height:n.innerHeight}:null;return angular.extend({},s,d,f,u)}function E(e,t,n,a){var o,i=e.split('-');switch(i[0]){case'right':o={top:t.top+t.height/2-a/2,left:t.left+t.width};break;case'bottom':o={top:t.top+t.height,left:t.left+t.width/2-n/2};break;case'left': +o={top:t.top+t.height/2-a/2,left:t.left-n};break;default:o={top:t.top-a,left:t.left+t.width/2-n/2}}if(!i[1])return o;if('top'===i[0]||'bottom'===i[0])switch(i[1]){case'left':o.left=t.left;break;case'right':o.left=t.left+t.width-n}else if('left'===i[0]||'right'===i[0])switch(i[1]){case'top':o.top=t.top-a;break;case'bottom':o.top=t.top+t.height}return o}function A(e,t){var n=z[0],a=n.offsetWidth,o=n.offsetHeight,i=parseInt(c.css(n,'margin-top'),10),r=parseInt(c.css(n,'margin-left'),10);isNaN(i)&&(i=0),isNaN(r)&&(r=0),e.top=e.top+i,e.left=e.left+r,c.setOffset(n,angular.extend({using:function(e){z.css({top:Math.round(e.top)+'px',left:Math.round(e.left)+'px',right:''})}},e),0);var s=n.offsetWidth,l=n.offsetHeight;if('top'===t&&l!==o&&(e.top=e.top+o-l),!/top-left|top-right|bottom-left|bottom-right/.test(t)){var u=F(t,e,s,l);if(u.left?e.left+=u.left:e.top+=u.top,c.setOffset(n,e),/top|right|bottom|left/.test(t)){var d=/top|bottom/.test(t),f=d?2*u.left-a+s:2*u.top-o+l,p=d?'offsetWidth':'offsetHeight';V(f,n[p],d)}}}function F(e,t,n,a){var o={top:0,left:0},i=H.viewport&&m(H.viewport.selector||H.viewport);if(!i)return o;var r=H.viewport&&H.viewport.padding||0,s=M(i);if(/right|left/.test(e)){var l=t.top-r-s.scroll,u=t.top+r-s.scroll+a;ls.top+s.height&&(o.top=s.top+s.height-u)}else{var c=t.left-r,d=t.left+r+n;cs.width&&(o.left=s.left+s.width-d)}return o}function V(e,t,n){var a=m('.tooltip-arrow, .arrow',z[0]);a.css(n?'left':'top',50*(1-e/t)+'%').css(n?'top':'left','')}function O(){clearTimeout(R),I.$isShown&&null!==z&&(H.autoClose&&T(),H.keyboard&&S()),j&&(j.$destroy(),j=null),z&&(z.remove(),z=I.$element=null)}var I={},P=i[0].nodeName.toLowerCase(),H=I.$options=angular.extend({},e,r);I.$promise=$(H.template);var N=I.$scope=H.scope&&H.scope.$new()||a.$new();if(H.delay&&angular.isString(H.delay)){var L=H.delay.split(',').map(parseFloat);H.delay=L.length>1?{show:L[0],hide:L[1]}:L[0]}I.$id=H.id||i.attr('id')||'',H.title&&(N.title=u.trustAsHtml(H.title)),N.$setEnabled=function(e){N.$$postDigest(function(){I.setEnabled(e)})},N.$hide=function(){N.$$postDigest(function(){I.hide()})},N.$show=function(){N.$$postDigest(function(){I.show()})},N.$toggle=function(){N.$$postDigest(function(){I.toggle()})},I.$isShown=N.$isShown=!1;var R,Y;H.contentTemplate&&(I.$promise=I.$promise.then(function(e){var t=angular.element(e);return $(H.contentTemplate).then(function(e){var n=m('[ng-bind="content"]',t[0]);return n.length||(n=m('[ng-bind="title"]',t[0])),n.removeAttr('ng-bind').html(e),t[0].outerHTML})}));var q,z,K,U,j;I.$promise.then(function(e){angular.isObject(e)&&(e=e.data),H.html&&(e=e.replace(w,'ng-bind-html="')),e=h.apply(e),K=e,q=o(e),I.init()}),I.init=function(){H.delay&&angular.isNumber(H.delay)&&(H.delay={show:H.delay,hide:H.delay}),'self'===H.container?U=i:angular.isElement(H.container)?U=H.container:H.container&&(U=m(H.container)),b(),H.target&&(H.target=angular.isElement(H.target)?H.target:m(H.target)),H.show&&N.$$postDigest(function(){'focus'===H.trigger?i[0].focus():I.show()})},I.destroy=function(){D(),O(),N.$destroy()},I.enter=function(){return clearTimeout(R),Y='in',H.delay&&H.delay.show?void(R=setTimeout(function(){'in'===Y&&I.show()},H.delay.show)):I.show()},I.show=function(){if(H.bsEnabled&&!I.$isShown){N.$emit(H.prefixEvent+'.show.before',I);var e,t;H.container?(e=U,t=U[0].lastChild?angular.element(U[0].lastChild):null):(e=null,t=i),z&&O(),j=I.$scope.$new(),z=I.$element=q(j,function(e,t){}),z.css({top:'-9999px',left:'-9999px',right:'auto',display:'block',visibility:'hidden'}),H.animation&&z.addClass(H.animation),H.type&&z.addClass(H.prefixClass+'-'+H.type),H.customClass&&z.addClass(H.customClass),t?t.after(z):e.prepend(z),I.$isShown=N.$isShown=!0,g(N),I.$applyPlacement();var n=l.enter(z,e,t,s);n&&n.then&&n.then(s),g(N),d(function(){z&&z.css({visibility:'visible'})}),H.keyboard&&('focus'!==H.trigger&&I.focus(),k()),H.autoClose&&x()}},I.leave=function(){return clearTimeout(R),Y='out',H.delay&&H.delay.hide?void(R=setTimeout(function(){'out'===Y&&I.hide()},H.delay.hide)):I.hide()};var W,B;I.hide=function(e){if(I.$isShown){N.$emit(H.prefixEvent+'.hide.before',I),W=e,B=z;var t=l.leave(z,p);t&&t.then&&t.then(p),I.$isShown=N.$isShown=!1,g(N),H.keyboard&&null!==z&&S(),H.autoClose&&null!==z&&T()}},I.toggle=function(){I.$isShown?I.leave():I.enter()},I.focus=function(){z[0].focus()},I.setEnabled=function(e){H.bsEnabled=e},I.setViewport=function(e){H.viewport=e},I.$applyPlacement=function(){if(z){var t=H.placement,n=/\s?auto?\s?/i,a=n.test(t);a&&(t=t.replace(n,'')||e.placement),z.addClass(H.placement);var o=M(),r=z.prop('offsetWidth'),s=z.prop('offsetHeight');if(a){var l=t,u=H.container?m(H.container):i.parent(),c=M(u);l.indexOf('bottom')>=0&&o.bottom+s>c.bottom?t=l.replace('bottom','top'):l.indexOf('top')>=0&&o.top-sc.width?t='right'===l?'left':t.replace('left','right'):('left'===l||'bottom-right'===l||'top-right'===l)&&o.left-r=e.length&&(u.$activeIndex=s.autoSelect?0:-1),/^(bottom|bottom-left|bottom-right)$/.test(s.placement)||o(r.$applyPlacement)},r.activate=function(e){u.$activeIndex=e},r.select=function(e){if(-1!==e){var t=u.$matches[e].value;n.$setViewValue(t),n.$render(),u.$resetMatches(),l&&l.$digest(),u.$emit(s.prefixEvent+'.select',t,e,r)}},r.$isVisible=function(){return s.minLength&&n?u.$matches.length&&angular.isString(n.$viewValue)&&n.$viewValue.length>=s.minLength:!!u.$matches.length},r.$getIndex=function(e){var t=u.$matches.length,n=t;if(t){for(n=t;n--&&u.$matches[n].value!==e;);if(!(0>n))return n}},r.$onMouseDown=function(e){e.preventDefault(),e.stopPropagation()},r.$onKeyDown=function(e){/(38|40|13)/.test(e.keyCode)&&(!r.$isVisible()||13===e.keyCode&&-1===u.$activeIndex||(e.preventDefault(),e.stopPropagation()),13===e.keyCode&&u.$matches.length?r.select(u.$activeIndex):38===e.keyCode&&u.$activeIndex>0?u.$activeIndex--:40===e.keyCode&&u.$activeIndex0)return void s.$setViewValue(s.$viewValue.substring(0,s.$viewValue.length-1));e.length>d&&(e=e.slice(0,d));var n=m.$isVisible();n&&m.update(e),(1!==e.length||e[0].value!==t)&&(!n&&m.update(e),s.$render())})}),s.$formatters.push(function(e){var t=g.displayValue(e);return t===n?'':t}),s.$render=function(){if(s.$isEmpty(s.$viewValue))return t.val('');var e=m.$getIndex(s.$modelValue),n=angular.isDefined(e)?m.$scope.$matches[e].label:s.$viewValue;n=angular.isObject(n)?g.displayValue(n):n;var a=n?n.toString().replace(/<(?:.|\n)*?>/gm,''):'';t.val(l.trimValue===!1?a:a.trim())},e.$on('$destroy',function(){m&&m.destroy(),l=null,m=null})}}}])}(window,document); //# sourceMappingURL=angular-strap.min.js.map \ No newline at end of file diff --git a/dist/angular-strap.min.js.map b/dist/angular-strap.min.js.map index bfcb9ad58..275447aa7 100644 --- a/dist/angular-strap.min.js.map +++ b/dist/angular-strap.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["angular-strap.js","affix/affix.js","alert/alert.js","aside/aside.js","button/button.js","collapse/collapse.js","datepicker/datepicker.js","dropdown/dropdown.js","helpers/date-formatter.js","helpers/date-parser.js","helpers/debounce.js","helpers/dimensions.js","helpers/parse-options.js","helpers/raf.js","modal/modal.js","navbar/navbar.js","popover/popover.js","scrollspy/scrollspy.js","select/select.js","timepicker/timepicker.js","tab/tab.js","tooltip/tooltip.js","typeahead/typeahead.js"],"names":["window","document","undefined","angular","bodyEl","$window","body","windowEl","defaults","AffixFactory","offsetTop","$affix","inlineStyles","options","this","$get","reset","setWidth","initialAffixTop","offsetParent","match","getRequiredAffixClass","unpin","position","top","scrollTop","getScrollTop","scrollHeight","getScrollHeight","targetEl","pageYOffset","directive","parent","target","initialOffsetTop","offsetBottom","affixed","element","init","i","$parseOffsets","on","checkPosition","require","checkPositionWithEventLoop","dimensions","offset","destroy","style","width","off","affix","setTimeout","elementHeight","height","css","addClass","offsetUnpin","offsetHeight","offsetWidth","$debouncedOnResize","$onResize","initialPosition","restrict","affixTarget","$element","forEach","link","key","scope","option","$on","attr","test","controller","animation","prefixClass","container","provider","backdrop","keyboard","show","duration","type","dismissable","AlertFactory","$alert","$scope","config","extend","$timeout","hide","isDefined","falseValueRegExp","hasOwnProperty","title","newValue","oldValue","trustAsHtml","bsAlert","$observe","content","alert","trigger","toggle","module","contentTemplate","html","AsideFactory","$aside","requestAnimationFrame","$modal","bsAside","$watch","aside","activeClass","compile","children","querySelectorAll","childEl","ngModel","removeAttr","child","$button","constantValueRegExp","isInput","trueValue","falseValue","hasExoticValues","viewValue","$formatters","push","$render","modelValue","isActive","equals","checked","activeElement","bind","toggleEvent","$modelValue","$$rAF","$setViewValue","toggleClass","$apply","hasClass","value","nodeName","self","startCollapsed","allowMultiple","$attrs","activeIndexes","$targets","$active","length","index","indexOf","activeItems","splice","activateItem","$options","$collapse","copy","$toggles","$unregisterToggle","$registerToggle","$unregisterTarget","deactivateItem","$viewChangeListeners","fn","fixActiveItemIndexes","$setActive","disallowToggle","$activeIndexes","bsCollapseCtrl","controllers","$animate","ngModelCtrl","attrs","isArray","bsCollapseToggle","$registerTarget","render","active","action","delay","useNative","dateType","dateFormat","timezone","modelDateFormat","dayFormat","monthFormat","yearFormat","monthTitleFormat","yearTitleFormat","strictFormat","autoclose","minDate","Infinity","maxDate","startView","minView","startWeek","daysOfWeekDisabled","iconLeft","iconRight","isNative","DatepickerFactory","parentScope","$datepicker","pickerViews","views","el","selected","date","focus","viewDate","$iconLeft","$iconRight","$picker","$views","$mode","datepickerViews","$selectPane","$toggleMode","setMode","select","isDate","$build","updateDisabledDates","disabledDateRanges","dateRanges","$date","$dateValue","keep","Date","year","getFullYear","month","getDate","mode","pristine","call","$updateSelected","rows","built","$isSelected","$setDisabledEl","disabled","isDisabled","steps","targetDate","getUTCFullYear","getUTCMonth","UTC","$onMouseDown","evt","preventDefault","stopPropagation","isTouch","getUTCDate","$onKeyDown","keyCode","shiftKey","altKey","updateSelected","onKeyDown","$digest","prop","focusElement","_init","_destroy","_show","_hide","blur","previousValue","normalizeDateRanges","ranges","disabledRanges","datepicker","isMaxValid","isValid","isMinValid","isNaN","parsedDate","getTime","$parsers","unshift","$setValidity","getDateFormattedString","formatDate","bsShow","lang","format","$dateFormatter","dateParser","$dateParser","strict","validateAgainstMinMaxDate","getDateForAttribute","disabledDates","parse","timezoneOffsetAdjust","isUndefined","NaN","daySplit","arr","mod","n","m","arrays","size","$sce","weekDaysMin","weekdaysShort","weekDaysLabelsHtml","startDate","picker","weekDaysLabels","slice","concat","split","getMonth","update","firstDayOfMonth","firstDate","getDay","today","firstDateOffset","build","day","days","isToday","toDateString","label","muted","showLabels","labels","time","isSelected","newDate","name","firstMonth","months","lastDate","actualMonth","parseInt","firstYear","years","actualYear","setYear","placement","matchesSelector","DropdownFactory","$dropdown","onBodyClick","items","$rootScope","$new","parentEl","$isShown","removeClass","prototype","transclusion","bsDropdown","dropdown","isString","getDefaultLocale","id","splitTimeFormat","timeFormat","exec","DATETIME_FORMATS","$locale","getDatetimeFormat","SHORTDAY","hoursFormat","minutesFormat","secondsFormat","timeSeparator","showSeconds","dateFilter","ParseDate","seconds","$localeProvider","milliseconds","hours","array","isNumeric","parseFloat","isFinite","indexOfCaseInsensitive","len","str","toString","toLowerCase","DateParserFactory","minutes","getHours","getMilliseconds","getMinutes","proto","noop","toDate","regExpMap","sss","mm","keys","setFnMap","map","clonedFormat","search","v","sortedMap","regExpForFormat","re","join","text","replace","Object","escapeReservedSymbols","RegExp","regex","HH","H","hh","h","a","EEEE","EEE","dd","d","MMMM","MMM","SHORTMONTH","MM","M","DAY","yyyy","yy","y","MONTH","ss","setSeconds","s","setMinutes","setHours","setDate","setMonth","setFullYear","$format","baseDate","setMap","formatRegex","formatSetMap","setMapForFormat","matches","fromDate","substr","getTimeForAttribute","daylightSavingAdjust","undo","func","timeout","context","factory","immediate","apply","args","cancel","callNow","leading","trailing","wait","currentStyle","getComputedStyle","extra","boxRect","getBoundingClientRect","left","docElement","ownerDocument","curPosition","curLeft","curCSSTop","documentElement","clientTop","pageXOffset","scrollLeft","clientLeft","curCSSLeft","calculatePosition","curTop","curOffset","curElem","props","isFunction","using","offsetParentRect","offsetParentElement","outer","$parseOptions","$values","regexp","$match","displayFn","locals","valueName","valueFn","ParseOptionsFactory","groupByFn","valuesFn","$parse","keyName","cancelAnimationFrame","when","values","parseValues","raf","webkitRequestAnimationFrame","mozRequestAnimationFrame","rafSupported","timer","prefixEvent","template","trim","bodyElement","htmlReplaceRegExp","ModalFactory","enterAnimateCallback","promise","modalElement","leaveAnimateCallback","currentTarget","safeDigest","preventEventDefault","$hide","$$postDigest","$id","$show","$promise","templateEl","fetchTemplate","outerHTML","then","modalLinker","backdropElement","right","z-index","data","$compile","remove","$destroy","after","isElement","$emit","defaultPrevented","clonedElement","display","enter","hideOnBackdropClick","$onKeyUp","leave","which","fetchPromises","cache","$templateCache","res","$http","get","bsModal","modal","routeAttr","$navbar","liElements","li","liElement","pattern","path","autoClose","$popover","PopoverFactory","$tooltip","dataTarget","popover","bsPopover","isObject","$applyPlacement","setViewport","viewport","spies","$document","debounce","throttle","ScrollSpyFactory","scrollEl","isWindowSpy","scrollId","$$count","$scrollspy","unbindViewContentLoaded","unbindIncludeContentLoaded","trackedElements","$trackedElements","sortedElements","activeTarget","debouncedCheckPosition","viewportHeight","throttledCheckPosition","debouncedCheckOffsets","checkOffsets","docEl","$activateElement","source","$getTrackedElement","filter","targetElement","querySelector","trackedElement","b","trackElement","toDelete","untrackElement","activate","scrollspy","multiple","allNoneButtons","sort","caretHtml","placeholder","allText","noneText","maxLength","maxLengthHtml","iconCheckmark","SelectFactory","$select","$activeIndex","$isMultiple","$showAllNoneButtons","$allText","$iconCheckmark","$isActive","$isVisible","$selectNone","$matches","$updateActiveIndex","$getIndex","minLength","$viewValue","l","dataMultiple","inputEl","watchedOptions","$watchCollection","parsedOptions","bsOptions","$isEmpty","timeType","modelTimeFormat","minTime","maxTime","hourStep","minuteStep","secondStep","roundDisplay","iconUp","iconDown","arrowBehavior","timepickerFactory","hour","meridian","coeff","selRange","end","start","setSelectionRange","collapse","selectionStart","moveStart","selectionEnd","moveEnd","$timepicker","floorMinutes","floor","selectedIndex","defaultDate","second","getSeconds","millisecond","$iconUp","$iconDown","$moveIndex","$switchMeridian","switchMeridian","minute","midIndex","$isDisabled","showAM","isAM","selectedTime","$arrowAction","$setTimeByStep","hoursLength","triggerHandler","secondsLength","sepLength","lateralMove","count","minutesLength","selectRange","incr","isSeconds","isMeridian","createSelection","createTextRange","parsedTime","getTimeFormattedString","timepicker","validateAgainstMinMaxTime","navClass","$activeClass","$panes","$activePaneChangeListeners","$push","pane","$remove","activeIndex","$tab","transclude","templateUrl","postLink","bsTabsCtrl","bsActivePane","parsedBsActivePane","assign","customClass","bsEnabled","selector","padding","String","$body","_tipToHide","tipElement","triggers","unbindTriggerEvents","bindKeyboardEvents","$onFocusElementMouseDown","unbindKeyboardEvents","_autoCloseEventsBinded","bindAutoCloseEvents","unbindAutoCloseEvents","stopEventPropagation","event","getPosition","rect","elRect","p","scroll","isBody","getCalculatedOffset","actualWidth","actualHeight","outerDims","clientWidth","innerHeight","tip","marginTop","marginLeft","setOffset","delta","getViewportAdjustedDelta","isVertical","replaceArrow","arrowDelta","arrowOffsetPosition","viewportPadding","topEdgeOffset","$viewport","viewportDimensions","leftEdgeOffset","rightEdgeOffset","dimension","isHorizontal","findElement","$arrow","clearTimeout","tipScope","$$phase","$setEnabled","setEnabled","isEnabled","contentEl","tipLinker","tipTemplate","isNumber","tipContainer","bindTriggerEvents","destroyTipElement","hoverState","lastChild","visibility","prepend","_blur","elementPosition","autoPlace","originalPlacement","containerPosition","tipHeight","tipPosition","applyPlacement","tipWidth","TooltipFactory","$location","tooltip","bsTooltip","limit","autoSelect","comparator","trimValue","$typeahead","$resetMatches","TypeaheadFactory","typeahead","watchOptions","selectMode","isVisible","displayValue","val"],"mappings":"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","file":"angular-strap.min.js","sourcesContent":["(function(window, document, undefined) {\n'use strict';\n\n// Source: module.js\nangular.module('mgcrea.ngStrap', [\n 'mgcrea.ngStrap.modal',\n 'mgcrea.ngStrap.aside',\n 'mgcrea.ngStrap.alert',\n 'mgcrea.ngStrap.button',\n 'mgcrea.ngStrap.select',\n 'mgcrea.ngStrap.datepicker',\n 'mgcrea.ngStrap.timepicker',\n 'mgcrea.ngStrap.navbar',\n 'mgcrea.ngStrap.tooltip',\n 'mgcrea.ngStrap.popover',\n 'mgcrea.ngStrap.dropdown',\n 'mgcrea.ngStrap.typeahead',\n 'mgcrea.ngStrap.scrollspy',\n 'mgcrea.ngStrap.affix',\n 'mgcrea.ngStrap.tab',\n 'mgcrea.ngStrap.collapse'\n]);\n\n// Source: affix/affix.js\nangular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mgcrea.ngStrap.helpers.debounce'])\n\n .provider('$affix', function() {\n\n var defaults = this.defaults = {\n offsetTop: 'auto',\n inlineStyles: true\n };\n\n this.$get = function($window, debounce, dimensions) {\n\n var bodyEl = angular.element($window.document.body);\n var windowEl = angular.element($window);\n\n function AffixFactory(element, config) {\n\n var $affix = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var targetEl = options.target;\n\n // Initial private vars\n var reset = 'affix affix-top affix-bottom',\n setWidth = false,\n initialAffixTop = 0,\n initialOffsetTop = 0,\n offsetTop = 0,\n offsetBottom = 0,\n affixed = null,\n unpin = null;\n\n var parent = element.parent();\n // Options: custom parent\n if (options.offsetParent) {\n if (options.offsetParent.match(/^\\d+$/)) {\n for (var i = 0; i < (options.offsetParent * 1) - 1; i++) {\n parent = parent.parent();\n }\n }\n else {\n parent = angular.element(options.offsetParent);\n }\n }\n\n $affix.init = function() {\n\n this.$parseOffsets();\n initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n setWidth = !element[0].style.width;\n\n // Bind events\n targetEl.on('scroll', this.checkPosition);\n targetEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', this.$debouncedOnResize);\n\n // Both of these checkPosition() calls are necessary for the case where\n // the user hits refresh after scrolling to the bottom of the page.\n this.checkPosition();\n this.checkPositionWithEventLoop();\n\n };\n\n $affix.destroy = function() {\n\n // Unbind events\n targetEl.off('scroll', this.checkPosition);\n targetEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', this.$debouncedOnResize);\n\n };\n\n $affix.checkPositionWithEventLoop = function() {\n\n // IE 9 throws an error if we use 'this' instead of '$affix'\n // in this setTimeout call\n setTimeout($affix.checkPosition, 1);\n\n };\n\n $affix.checkPosition = function() {\n // if (!this.$element.is(':visible')) return\n\n var scrollTop = getScrollTop();\n var position = dimensions.offset(element[0]);\n var elementHeight = dimensions.height(element[0]);\n\n // Get required affix class according to position\n var affix = getRequiredAffixClass(unpin, position, elementHeight);\n\n // Did affix status changed this last check?\n if(affixed === affix) return;\n affixed = affix;\n\n // Add proper affix class\n element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\n\n if(affix === 'top') {\n unpin = null;\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', '');\n }\n } else if(affix === 'bottom') {\n if (options.offsetUnpin) {\n unpin = -(options.offsetUnpin * 1);\n }\n else {\n // Calculate unpin threshold when affixed to bottom.\n // Hopefully the browser scrolls pixel by pixel.\n unpin = position.top - scrollTop;\n }\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n }\n } else { // affix === 'middle'\n unpin = null;\n if(setWidth) {\n element.css('width', element[0].offsetWidth + 'px');\n }\n if (options.inlineStyles) {\n element.css('position', 'fixed');\n element.css('top', initialAffixTop + 'px');\n }\n }\n\n };\n\n $affix.$onResize = function() {\n $affix.$parseOffsets();\n $affix.checkPosition();\n };\n $affix.$debouncedOnResize = debounce($affix.$onResize, 50);\n\n $affix.$parseOffsets = function() {\n var initialPosition = element.css('position');\n // Reset position to calculate correct offsetTop\n if (options.inlineStyles){\n element.css('position', (options.offsetParent) ? '' : 'relative');\n }\n\n if(options.offsetTop) {\n if(options.offsetTop === 'auto') {\n options.offsetTop = '+0';\n }\n if(options.offsetTop.match(/^[-+]\\d+$/)) {\n initialAffixTop = - options.offsetTop * 1;\n if(options.offsetParent) {\n offsetTop = dimensions.offset(parent[0]).top + (options.offsetTop * 1);\n }\n else {\n offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\n }\n }\n else {\n offsetTop = options.offsetTop * 1;\n }\n }\n\n if(options.offsetBottom) {\n if(options.offsetParent && options.offsetBottom.match(/^[-+]\\d+$/)) {\n // add 1 pixel due to rounding problems...\n offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + (options.offsetBottom * 1) + 1;\n }\n else {\n offsetBottom = options.offsetBottom * 1;\n }\n }\n\n // Bring back the element's position after calculations\n if (options.inlineStyles){\n element.css('position', initialPosition);\n }\n };\n\n // Private methods\n\n function getRequiredAffixClass(unpin, position, elementHeight) {\n\n var scrollTop = getScrollTop();\n var scrollHeight = getScrollHeight();\n\n if(scrollTop <= offsetTop) {\n return 'top';\n } else if(unpin !== null && (scrollTop + unpin <= position.top)) {\n return 'middle';\n } else if(offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n return 'bottom';\n } else {\n return 'middle';\n }\n\n }\n\n function getScrollTop() {\n return targetEl[0] === $window ? $window.pageYOffset : targetEl[0].scrollTop;\n }\n\n function getScrollHeight() {\n return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight;\n }\n\n $affix.init();\n return $affix;\n\n }\n\n return AffixFactory;\n\n };\n\n })\n\n .directive('bsAffix', function($affix, $window) {\n\n return {\n restrict: 'EAC',\n require: '^?bsAffixTarget',\n link: function postLink(scope, element, attr, affixTarget) {\n\n var options = {scope: scope, target: affixTarget ? affixTarget.$element : angular.element($window)};\n angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin', 'inlineStyles'], function(key) {\n if(angular.isDefined(attr[key])) {\n var option = attr[key];\n if (/true/i.test(option)) option = true;\n if (/false/i.test(option)) option = false;\n options[key] = option;\n }\n });\n\n var affix = $affix(element, options);\n scope.$on('$destroy', function() {\n affix && affix.destroy();\n options = null;\n affix = null;\n });\n\n }\n };\n\n })\n\n .directive('bsAffixTarget', function() {\n return {\n controller: function($element) {\n this.$element = $element;\n }\n };\n });\n\n// Source: alert/alert.js\n// @BUG: following snippet won't compile correctly\n// @TODO: submit issue to core\n// ' ' +\n\nangular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal'])\n\n .provider('$alert', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'alert',\n prefixEvent: 'alert',\n placement: null,\n template: 'alert/alert.tpl.html',\n container: false,\n element: null,\n backdrop: false,\n keyboard: true,\n show: true,\n // Specific options\n duration: false,\n type: false,\n dismissable: true\n };\n\n this.$get = function($modal, $timeout) {\n\n function AlertFactory(config) {\n\n var $alert = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $alert = $modal(options);\n\n // Support scope as string options [/*title, content, */ type, dismissable]\n $alert.$scope.dismissable = !!options.dismissable;\n if(options.type) {\n $alert.$scope.type = options.type;\n }\n\n // Support auto-close duration\n var show = $alert.show;\n if(options.duration) {\n $alert.show = function() {\n show();\n $timeout(function() {\n $alert.hide();\n }, options.duration * 1000);\n };\n }\n\n return $alert;\n\n }\n\n return AlertFactory;\n\n };\n\n })\n\n .directive('bsAlert', function($window, $sce, $alert) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'placement', 'keyboard', 'html', 'container', 'animation', 'duration', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['keyboard', 'html', 'container', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content', 'type'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAlert && scope.$watch(attr.bsAlert, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize alert\n var alert = $alert(options);\n\n // Trigger\n element.on(attr.trigger || 'click', alert.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (alert) alert.destroy();\n options = null;\n alert = null;\n });\n\n }\n };\n\n });\n\n// Source: aside/aside.js\nangular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal'])\n\n .provider('$aside', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade-and-slide-right',\n prefixClass: 'aside',\n prefixEvent: 'aside',\n placement: 'right',\n template: 'aside/aside.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($modal) {\n\n function AsideFactory(config) {\n\n var $aside = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $aside = $modal(options);\n\n return $aside;\n\n }\n\n return AsideFactory;\n\n };\n\n })\n\n .directive('bsAside', function($window, $sce, $aside) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAside && scope.$watch(attr.bsAside, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize aside\n var aside = $aside(options);\n\n // Trigger\n element.on(attr.trigger || 'click', aside.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (aside) aside.destroy();\n options = null;\n aside = null;\n });\n\n }\n };\n\n });\n\n// Source: button/button.js\nangular.module('mgcrea.ngStrap.button', [])\n\n .provider('$button', function() {\n\n var defaults = this.defaults = {\n activeClass:'active',\n toggleEvent:'click'\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsCheckboxGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"checkbox\"]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.attr('bs-checkbox', '');\n childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));\n });\n }\n\n };\n\n })\n\n .directive('bsCheckbox', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support label > input[type=\"checkbox\"]\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;\n if(constantValueRegExp.test(attr.trueValue)) {\n trueValue = scope.$eval(attr.trueValue);\n }\n var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;\n if(constantValueRegExp.test(attr.falseValue)) {\n falseValue = scope.$eval(attr.falseValue);\n }\n\n // Parse exotic values\n var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';\n if(hasExoticValues) {\n controller.$parsers.push(function(viewValue) {\n // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue);\n return viewValue ? trueValue : falseValue;\n });\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n return angular.equals(modelValue, trueValue);\n });\n // Fix rendering for exotic values\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n controller.$render();\n });\n }\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, trueValue);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n if(!isInput) {\n controller.$setViewValue(!activeElement.hasClass('active'));\n }\n if(!hasExoticValues) {\n controller.$render();\n }\n });\n });\n\n }\n\n };\n\n })\n\n .directive('bsRadioGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"radio\"]');\n angular.forEach(children, function(child) {\n angular.element(child).attr('bs-radio', '');\n angular.element(child).attr('ng-model', attr.ngModel);\n });\n }\n\n };\n\n })\n\n .directive('bsRadio', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support `label > input[type=\"radio\"]` markup\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var value;\n attr.$observe('value', function(v) {\n value = constantValueRegExp.test(v) ? scope.$eval(v) : v;\n controller.$render();\n });\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, value);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n controller.$setViewValue(value);\n controller.$render();\n });\n });\n\n }\n\n };\n\n });\n\n// Source: collapse/collapse.js\nangular.module('mgcrea.ngStrap.collapse', [])\n\n .provider('$collapse', function() {\n\n var defaults = this.defaults = {\n animation: 'am-collapse',\n disallowToggle: false,\n activeClass: 'in',\n startCollapsed: false,\n allowMultiple: false\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['disallowToggle', 'startCollapsed', 'allowMultiple'], function(key) {\n if(angular.isDefined($attrs[key]) && falseValueRegExp.test($attrs[key]))\n self.$options[key] = false;\n });\n\n self.$toggles = [];\n self.$targets = [];\n\n self.$viewChangeListeners = [];\n\n self.$registerToggle = function(element) {\n self.$toggles.push(element);\n };\n self.$registerTarget = function(element) {\n self.$targets.push(element);\n };\n\n self.$unregisterToggle = function(element) {\n var index = self.$toggles.indexOf(element);\n // remove toggle from $toggles array\n self.$toggles.splice(index, 1);\n };\n self.$unregisterTarget = function(element) {\n var index = self.$targets.indexOf(element);\n\n // remove element from $targets array\n self.$targets.splice(index, 1);\n\n if (self.$options.allowMultiple) {\n // remove target index from $active array values\n deactivateItem(element);\n }\n\n // fix active item indexes\n fixActiveItemIndexes(index);\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n // use array to store all the currently open panels\n self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n self.$setActive = $scope.$setActive = function(value) {\n if(angular.isArray(value)) {\n self.$targets.$active = angular.copy(value);\n }\n else if(!self.$options.disallowToggle) {\n // toogle element active status\n isActive(value) ? deactivateItem(value) : activateItem(value);\n } else {\n activateItem(value);\n }\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$activeIndexes = function() {\n return self.$options.allowMultiple ? self.$targets.$active :\n self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n };\n\n function fixActiveItemIndexes(index) {\n // item with index was removed, so we\n // need to adjust other items index values\n var activeIndexes = self.$targets.$active;\n for(var i = 0; i < activeIndexes.length; i++) {\n if (index < activeIndexes[i]) {\n activeIndexes[i] = activeIndexes[i] - 1;\n }\n\n // the last item is active, so we need to\n // adjust its index\n if (activeIndexes[i] === self.$targets.length) {\n activeIndexes[i] = self.$targets.length - 1;\n }\n }\n }\n\n function isActive(value) {\n var activeItems = self.$targets.$active;\n return activeItems.indexOf(value) === -1 ? false : true;\n }\n\n function deactivateItem(value) {\n var index = self.$targets.$active.indexOf(value);\n if (index !== -1) {\n self.$targets.$active.splice(index, 1);\n }\n }\n\n function activateItem(value) {\n if (!self.$options.allowMultiple) {\n // remove current selected item\n self.$targets.$active.splice(0, 1);\n }\n\n if (self.$targets.$active.indexOf(value) === -1) {\n self.$targets.$active.push(value);\n }\n }\n\n };\n\n this.$get = function() {\n var $collapse = {};\n $collapse.defaults = defaults;\n $collapse.controller = controller;\n return $collapse;\n };\n\n })\n\n .directive('bsCollapse', function($window, $animate, $collapse) {\n\n var defaults = $collapse.defaults;\n\n return {\n require: ['?ngModel', 'bsCollapse'],\n controller: ['$scope', '$element', '$attrs', $collapse.controller],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n if (angular.isArray(modelValue)) {\n // model value is an array, so just replace\n // the active items directly\n bsCollapseCtrl.$setActive(modelValue);\n }\n else {\n var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n if (angular.isArray(activeIndexes)) {\n // we have an array of selected indexes\n if (activeIndexes.indexOf(modelValue * 1) === -1) {\n // item with modelValue index is not active\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n else if (activeIndexes !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n return modelValue;\n });\n\n }\n\n }\n };\n\n })\n\n .directive('bsCollapseToggle', function() {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base attr\n element.attr('data-toggle', 'collapse');\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerToggle(element);\n\n // remove toggle from collapse controller when toggle is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterToggle(element);\n });\n\n element.on('click', function() {\n var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n bsCollapseCtrl.$setActive(index * 1);\n scope.$apply();\n });\n\n }\n };\n\n })\n\n .directive('bsCollapseTarget', function($animate) {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n // scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base class\n element.addClass('collapse');\n\n // Add animation class\n if(bsCollapseCtrl.$options.animation) {\n element.addClass(bsCollapseCtrl.$options.animation);\n }\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerTarget(element);\n\n // remove pane target from collapse controller when target is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterTarget(element);\n });\n\n function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$activeIndexes();\n var action = 'removeClass';\n if (angular.isArray(active)) {\n if (active.indexOf(index) !== -1) {\n action = 'addClass';\n }\n }\n else if (index === active) {\n action = 'addClass';\n }\n\n $animate[action](element, bsCollapseCtrl.$options.activeClass);\n }\n\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n\n// Source: datepicker/datepicker.js\nangular.module('mgcrea.ngStrap.datepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$datepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'datepicker',\n prefixClass: 'datepicker',\n placement: 'bottom-left',\n template: 'datepicker/datepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: false,\n dateType: 'date',\n dateFormat: 'shortDate',\n timezone: null,\n modelDateFormat: null,\n dayFormat: 'dd',\n monthFormat: 'MMM',\n yearFormat: 'yyyy',\n monthTitleFormat: 'MMMM yyyy',\n yearTitleFormat: 'yyyy',\n strictFormat: false,\n autoclose: false,\n minDate: -Infinity,\n maxDate: +Infinity,\n startView: 0,\n minView: 0,\n startWeek: 0,\n daysOfWeekDisabled: '',\n iconLeft: 'glyphicon glyphicon-chevron-left',\n iconRight: 'glyphicon glyphicon-chevron-right'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function DatepickerFactory(element, controller, config) {\n\n var $datepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $datepicker.$options;\n var scope = $datepicker.$scope;\n if(options.startView) options.startView -= options.minView;\n\n // View vars\n\n var pickerViews = datepickerViews($datepicker);\n $datepicker.$views = pickerViews.views;\n var viewDate = pickerViews.viewDate;\n scope.$mode = options.startView;\n scope.$iconLeft = options.iconLeft;\n scope.$iconRight = options.iconRight;\n var $picker = $datepicker.$views[scope.$mode];\n\n // Scope methods\n\n scope.$select = function(date) {\n $datepicker.select(date);\n };\n scope.$selectPane = function(value) {\n $datepicker.$selectPane(value);\n };\n scope.$toggleMode = function() {\n $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);\n };\n\n // Public methods\n\n $datepicker.update = function(date) {\n // console.warn('$datepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $datepicker.$date = date;\n $picker.update.call($picker, date);\n }\n // Build only if pristine\n $datepicker.$build(true);\n };\n\n $datepicker.updateDisabledDates = function(dateRanges) {\n options.disabledDateRanges = dateRanges;\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);\n }\n };\n\n $datepicker.select = function(date, keep) {\n // console.warn('$datepicker.select', date, scope.$mode);\n if(!angular.isDate(controller.$dateValue)) controller.$dateValue = new Date(date);\n if(!scope.$mode || keep) {\n controller.$setViewValue(angular.copy(date));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $datepicker.hide(true); });\n }\n } else {\n angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});\n $datepicker.setMode(scope.$mode - 1);\n $datepicker.$build();\n }\n };\n\n $datepicker.setMode = function(mode) {\n // console.warn('$datepicker.setMode', mode);\n scope.$mode = mode;\n $picker = $datepicker.$views[scope.$mode];\n $datepicker.$build();\n };\n\n // Protected methods\n\n $datepicker.$build = function(pristine) {\n // console.warn('$datepicker.$build() viewDate=%o', viewDate);\n if(pristine === true && $picker.built) return;\n if(pristine === false && !$picker.built) return;\n $picker.build.call($picker);\n };\n\n $datepicker.$updateSelected = function() {\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], updateSelected);\n }\n };\n\n $datepicker.$isSelected = function(date) {\n return $picker.isSelected(date);\n };\n\n $datepicker.$setDisabledEl = function(el) {\n el.disabled = $picker.isDisabled(el.date);\n };\n\n $datepicker.$selectPane = function(value) {\n var steps = $picker.steps;\n // set targetDate to first day of month to avoid problems with\n // date values rollover. This assumes the viewDate does not\n // depend on the day of the month\n var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));\n angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});\n $datepicker.$build();\n };\n\n $datepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $datepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n if(evt.keyCode === 13) {\n if(!scope.$mode) {\n return $datepicker.hide(true);\n } else {\n return scope.$apply(function() { $datepicker.setMode(scope.$mode - 1); });\n }\n }\n\n // Navigate with keyboard\n $picker.onKeyDown(evt);\n parentScope.$digest();\n };\n\n // Private\n\n function updateSelected(el) {\n el.selected = $datepicker.$isSelected(el.date);\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $datepicker.init;\n $datepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'date');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $datepicker.destroy;\n $datepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $datepicker.show;\n $datepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // if $datepicker is no longer showing, don't setup events\n if(!$datepicker.$isShown) return;\n $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $datepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $datepicker.hide;\n $datepicker.hide = function(blur) {\n if(!$datepicker.$isShown) return;\n $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $datepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $datepicker;\n\n }\n\n DatepickerFactory.defaults = defaults;\n return DatepickerFactory;\n\n };\n\n })\n\n .directive('bsDatepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {\n\n var defaults = $datepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'timezone', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!datepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);\n newValue === true ? datepicker.show() : datepicker.hide();\n });\n\n // Initialize datepicker\n var datepicker = $datepicker(element, controller, options);\n options = datepicker.$options;\n // Set expected iOS format\n if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';\n\n var lang = options.lang;\n\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n // Observe attributes for changes\n angular.forEach(['minDate', 'maxDate'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n // console.warn('attr.$observe(%s)=%o', key, newValue);\n datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);\n // Build only if dirty\n !isNaN(datepicker.$options[key]) && datepicker.$build(false);\n validateAgainstMinMaxDate(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n datepicker.update(controller.$dateValue);\n }, true);\n\n // Normalize undefined/null/empty array,\n // so that we don't treat changing from undefined->null as a change.\n function normalizeDateRanges(ranges) {\n if (!ranges || !ranges.length) return null;\n return ranges;\n }\n\n if (angular.isDefined(attr.disabledDates)) {\n scope.$watch(attr.disabledDates, function(disabledRanges, previousValue) {\n disabledRanges = normalizeDateRanges(disabledRanges);\n previousValue = normalizeDateRanges(previousValue);\n\n if (disabledRanges) {\n datepicker.updateDisabledDates(disabledRanges);\n }\n });\n }\n\n function validateAgainstMinMaxDate(parsedDate) {\n if (!angular.isDate(parsedDate)) return;\n var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;\n var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(isValid) controller.$dateValue = parsedDate;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n controller.$setValidity('date', true);\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n return null;\n }\n var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedDate || isNaN(parsedDate.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxDate(parsedDate);\n }\n\n if(options.dateType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedDate, options.timezone, true);\n return formatDate(date, options.modelDateFormat || options.dateFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.dateType === 'number') {\n return date.getTime();\n } else if(options.dateType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.dateType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.dateType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelDateFormat);\n } else if(options.dateType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) {\n // var today = new Date();\n // date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n // }\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getDateFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getDateFormattedString());\n };\n\n function getDateFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(datepicker) datepicker.destroy();\n options = null;\n datepicker = null;\n });\n\n }\n };\n\n })\n\n .provider('datepickerViews', function() {\n\n var defaults = this.defaults = {\n dayFormat: 'dd',\n daySplit: 7\n };\n\n // Split array into smaller arrays\n function split(arr, size) {\n var arrays = [];\n while(arr.length > 0) {\n arrays.push(arr.splice(0, size));\n }\n return arrays;\n }\n\n // Modulus operator\n function mod(n, m) {\n return ((n % m) + m) % m;\n }\n\n this.$get = function($dateFormatter, $dateParser, $sce) {\n\n return function(picker) {\n\n var scope = picker.$scope;\n var options = picker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n var weekDaysLabelsHtml = $sce.trustAsHtml('' + weekDaysLabels.join('') + '');\n\n var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n\n var views = [{\n format: options.dayFormat,\n split: 7,\n steps: { month: 1 },\n update: function(date, force) {\n if(!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getDate() !== viewDate.date || date.getDate() === 1) {\n // chaging picker current month will cause viewDate.date to be set to first day of the month,\n // in $datepicker.$selectPane, so picker would not update selected day display if\n // user picks first day of the new month.\n // As a workaround, we are always forcing update when picked date is first day of month.\n viewDate.date = picker.$date.getDate();\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5), firstDateOffset = firstDate.getTimezoneOffset();\n var today = dateParser.timezoneOffsetAdjust(new Date(), options.timezone).toDateString();\n // Handle daylight time switch\n if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);\n var days = [], day;\n for(var i = 0; i < 42; i++) { // < 7 * 6\n day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));\n days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n }\n scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);\n scope.showLabels = true;\n scope.labels = weekDaysLabelsHtml;\n scope.rows = split(days, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();\n },\n isDisabled: function(date) {\n var time = date.getTime();\n\n // Disabled because of min/max date.\n if (time < options.minDate || time > options.maxDate) return true;\n\n // Disabled due to being a disabled day of the week\n if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;\n\n // Disabled because of disabled date range.\n if (options.disabledDateRanges) {\n for (var i = 0; i < options.disabledDateRanges.length; i++) {\n if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {\n return true;\n }\n }\n }\n\n return false;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualTime = picker.$date.getTime();\n var newDate;\n\n if(evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);\n else if(evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);\n else if(evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);\n else if(evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'month',\n format: options.monthFormat,\n split: 4,\n steps: { year: 1 },\n update: function(date, force) {\n if(!this.built || date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstMonth = new Date(viewDate.year, 0, 1);\n var months = [], month;\n for (var i = 0; i < 12; i++) {\n month = new Date(viewDate.year, i, 1);\n months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n }\n scope.title = formatDate(month, options.yearTitleFormat);\n scope.showLabels = false;\n scope.rows = split(months, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualMonth = picker.$date.getMonth();\n var newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setMonth(actualMonth - 1);\n else if(evt.keyCode === 38) newDate.setMonth(actualMonth - 4);\n else if(evt.keyCode === 39) newDate.setMonth(actualMonth + 1);\n else if(evt.keyCode === 40) newDate.setMonth(actualMonth + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'year',\n format: options.yearFormat,\n split: 4,\n steps: { year: 12 },\n update: function(date, force) {\n if(!this.built || force || parseInt(date.getFullYear()/20, 10) !== parseInt(viewDate.year/20, 10)) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstYear = viewDate.year - viewDate.year % (this.split * 3);\n var years = [], year;\n for (var i = 0; i < 12; i++) {\n year = new Date(firstYear + i, 0, 1);\n years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});\n }\n scope.title = years[0].label + '-' + years[years.length - 1].label;\n scope.showLabels = false;\n scope.rows = split(years, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear() + 1, 0, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualYear = picker.$date.getFullYear(),\n newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setYear(actualYear - 1);\n else if(evt.keyCode === 38) newDate.setYear(actualYear - 4);\n else if(evt.keyCode === 39) newDate.setYear(actualYear + 1);\n else if(evt.keyCode === 40) newDate.setYear(actualYear + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }];\n\n return {\n views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,\n viewDate: viewDate\n };\n\n };\n\n };\n\n });\n\n// Source: dropdown/dropdown.js\nangular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$dropdown', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'dropdown',\n prefixEvent: 'dropdown',\n placement: 'bottom-left',\n template: 'dropdown/dropdown.tpl.html',\n trigger: 'click',\n container: false,\n keyboard: true,\n html: false,\n delay: 0\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;\n\n function DropdownFactory(element, config) {\n\n var $dropdown = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n $dropdown = $tooltip(element, options);\n var parentEl = element.parent();\n\n // Protected methods\n\n $dropdown.$onKeyDown = function(evt) {\n if (!/(38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Retrieve focused index\n var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));\n if(!items.length) return;\n var index;\n angular.forEach(items, function(el, i) {\n if(matchesSelector && matchesSelector.call(el, ':focus')) index = i;\n });\n\n // Navigate with keyboard\n if(evt.keyCode === 38 && index > 0) index--;\n else if(evt.keyCode === 40 && index < items.length - 1) index++;\n else if(angular.isUndefined(index)) index = 0;\n items.eq(index)[0].focus();\n\n };\n\n // Overrides\n\n var show = $dropdown.show;\n $dropdown.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n bodyEl.on('click', onBodyClick);\n }, 0, false);\n parentEl.hasClass('dropdown') && parentEl.addClass('open');\n };\n\n var hide = $dropdown.hide;\n $dropdown.hide = function() {\n if(!$dropdown.$isShown) return;\n options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n bodyEl.off('click', onBodyClick);\n parentEl.hasClass('dropdown') && parentEl.removeClass('open');\n hide();\n };\n\n var destroy = $dropdown.destroy;\n $dropdown.destroy = function() {\n bodyEl.off('click', onBodyClick);\n destroy();\n };\n\n // Private functions\n\n function onBodyClick(evt) {\n if(evt.target === element[0]) return;\n return evt.target !== element[0] && $dropdown.hide();\n }\n\n return $dropdown;\n\n }\n\n return DropdownFactory;\n\n };\n\n })\n\n .directive('bsDropdown', function($window, $sce, $dropdown) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as an object\n attr.bsDropdown && scope.$watch(attr.bsDropdown, function(newValue, oldValue) {\n scope.content = newValue;\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!dropdown || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(dropdown),?/i);\n newValue === true ? dropdown.show() : dropdown.hide();\n });\n\n // Initialize dropdown\n var dropdown = $dropdown(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (dropdown) dropdown.destroy();\n options = null;\n dropdown = null;\n });\n\n }\n };\n\n });\n\n// Source: helpers/date-formatter.js\nangular.module('mgcrea.ngStrap.helpers.dateFormatter', [])\n\n .service('$dateFormatter', function($locale, dateFilter) {\n\n // The unused `lang` arguments are on purpose. The default implementation does not\n // use them and it always uses the locale loaded into the `$locale` service.\n // Custom implementations might use it, thus allowing different directives to\n // have different languages.\n\n this.getDefaultLocale = function() {\n return $locale.id;\n };\n\n // Format is either a data format name, e.g. \"shortTime\" or \"fullDate\", or a date format\n // Return either the corresponding date format or the given date format.\n this.getDatetimeFormat = function(format, lang) {\n return $locale.DATETIME_FORMATS[format] || format;\n };\n\n this.weekdaysShort = function(lang) {\n return $locale.DATETIME_FORMATS.SHORTDAY;\n };\n\n function splitTimeFormat(format) {\n return /(h+)([:\\.])?(m+)([:\\.])?(s*)[ ]?(a?)/i.exec(format).slice(1);\n }\n\n // h:mm a => h\n this.hoursFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[0];\n };\n\n // h:mm a => mm\n this.minutesFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[2];\n };\n\n // h:mm:ss a => ss\n this.secondsFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => :\n this.timeSeparator = function(timeFormat) {\n return splitTimeFormat(timeFormat)[1];\n };\n\n // h:mm:ss a => true, h:mm a => false\n this.showSeconds = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => true, H.mm => false\n this.showAM = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[5];\n };\n\n this.formatDate = function(date, format, lang, timezone){\n return dateFilter(date, format, timezone);\n };\n\n });\n\n// Source: helpers/date-parser.js\nangular.module('mgcrea.ngStrap.helpers.dateParser', [])\n\n.provider('$dateParser', function($localeProvider) {\n\n // define a custom ParseDate object to use instead of native Date\n // to avoid date values wrapping when setting date component values\n function ParseDate() {\n this.year = 1970;\n this.month = 0;\n this.day = 1;\n this.hours = 0;\n this.minutes = 0;\n this.seconds = 0;\n this.milliseconds = 0;\n }\n\n ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };\n ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };\n ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };\n ParseDate.prototype.setHours = function(value) { this.hours = value; };\n ParseDate.prototype.getHours = function() { return this.hours; };\n ParseDate.prototype.setDate = function(value) { this.day = value; };\n ParseDate.prototype.setMonth = function(value) { this.month = value; };\n ParseDate.prototype.setFullYear = function(value) { this.year = value; };\n ParseDate.prototype.fromDate = function(value) {\n this.year = value.getFullYear();\n this.month = value.getMonth();\n this.day = value.getDate();\n this.hours = value.getHours();\n this.minutes = value.getMinutes();\n this.seconds = value.getSeconds();\n this.milliseconds = value.getMilliseconds();\n return this;\n };\n\n ParseDate.prototype.toDate = function() {\n return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n };\n\n var proto = ParseDate.prototype;\n\n function noop() {\n }\n\n function isNumeric(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n function indexOfCaseInsensitive(array, value) {\n var len = array.length, str=value.toString().toLowerCase();\n for (var i=0; i 12 when midnight changeover, but then cannot generate\n * midnight datetime, so jump to 1AM, otherwise reset.\n * @param date (Date) the date to check\n * @return (Date) the corrected date\n *\n * __ copied from jquery ui datepicker __\n */\n $dateParser.daylightSavingAdjust = function(date) {\n if (!date) {\n return null;\n }\n date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n return date;\n };\n\n /* Correct the date for timezone offset.\n * @param date (Date) the date to adjust\n * @param timezone (string) the timezone to adjust for\n * @param undo (boolean) to add or subtract timezone offset\n * @return (Date) the corrected date\n */\n $dateParser.timezoneOffsetAdjust = function(date, timezone, undo) {\n if (!date) {\n return null;\n }\n // Right now, only 'UTC' is supported.\n if (timezone && timezone === 'UTC') {\n date = new Date(date.getTime());\n date.setMinutes(date.getMinutes() + (undo?-1:1)*date.getTimezoneOffset());\n }\n return date;\n };\n\n // Private functions\n\n function setMapForFormat(format) {\n var keys = Object.keys(setFnMap), i;\n var map = [], sortedMap = [];\n // Map to setFn\n var clonedFormat = format;\n for(i = 0; i < keys.length; i++) {\n if(format.split(keys[i]).length > 1) {\n var index = clonedFormat.search(keys[i]);\n format = format.split(keys[i]).join('');\n if(setFnMap[keys[i]]) {\n map[index] = setFnMap[keys[i]];\n }\n }\n }\n // Sort result map\n angular.forEach(map, function(v) {\n // conditional required since angular.forEach broke around v1.2.21\n // related pr: https://github.com/angular/angular.js/pull/8525\n if(v) sortedMap.push(v);\n });\n return sortedMap;\n }\n\n function escapeReservedSymbols(text) {\n return text.replace(/\\//g, '[\\\\/]').replace('/-/g', '[-]').replace(/\\./g, '[.]').replace(/\\\\s/g, '[\\\\s]');\n }\n\n function regExpForFormat(format) {\n var keys = Object.keys(regExpMap), i;\n\n var re = format;\n // Abstract replaces to avoid collisions\n for(i = 0; i < keys.length; i++) {\n re = re.split(keys[i]).join('${' + i + '}');\n }\n // Replace abstracted values\n for(i = 0; i < keys.length; i++) {\n re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');\n }\n format = escapeReservedSymbols(format);\n\n return new RegExp('^' + re + '$', ['i']);\n }\n\n $dateParser.init();\n return $dateParser;\n\n };\n\n return DateParserFactory;\n\n };\n\n});\n\n// Source: helpers/debounce.js\nangular.module('mgcrea.ngStrap.helpers.debounce', [])\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L693\n.factory('debounce', function($timeout) {\n return function(func, wait, immediate) {\n var timeout = null;\n return function() {\n var context = this,\n args = arguments,\n callNow = immediate && !timeout;\n if(timeout) {\n $timeout.cancel(timeout);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(!immediate) {\n func.apply(context, args);\n }\n }, wait, false);\n if(callNow) {\n func.apply(context, args);\n }\n return timeout;\n };\n };\n})\n\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L661\n.factory('throttle', function($timeout) {\n return function(func, wait, options) {\n var timeout = null;\n options || (options = {});\n return function() {\n var context = this,\n args = arguments;\n if(!timeout) {\n if(options.leading !== false) {\n func.apply(context, args);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(options.trailing !== false) {\n func.apply(context, args);\n }\n }, wait, false);\n }\n };\n };\n});\n\n// Source: helpers/dimensions.js\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n .factory('dimensions', function($document, $window) {\n\n var jqLite = angular.element;\n var fn = {};\n\n /**\n * Test the element nodeName\n * @param element\n * @param name\n */\n var nodeName = fn.nodeName = function(element, name) {\n return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();\n };\n\n /**\n * Returns the element computed style\n * @param element\n * @param prop\n * @param extra\n */\n fn.css = function(element, prop, extra) {\n var value;\n if (element.currentStyle) { //IE\n value = element.currentStyle[prop];\n } else if (window.getComputedStyle) {\n value = window.getComputedStyle(element)[prop];\n } else {\n value = element.style[prop];\n }\n return extra === true ? parseFloat(value) || 0 : value;\n };\n\n /**\n * Provides read-only equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.offset = function(element) {\n var boxRect = element.getBoundingClientRect();\n var docElement = element.ownerDocument;\n return {\n width: boxRect.width || element.offsetWidth,\n height: boxRect.height || element.offsetHeight,\n top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),\n left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)\n };\n };\n \n /**\n * Provides set equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip\n * @url http://api.jquery.com/offset/\n * @param element\n * @param options\n * @param i\n */\n fn.setOffset = function (element, options, i) {\n var curPosition,\n curLeft,\n curCSSTop,\n curTop,\n curOffset,\n curCSSLeft,\n calculatePosition,\n position = fn.css(element, 'position'),\n curElem = angular.element(element),\n props = {};\n \n // Set position first, in-case top/left are set even on static elem\n if (position === 'static') {\n element.style.position = 'relative';\n }\n \n curOffset = fn.offset(element);\n curCSSTop = fn.css(element, 'top');\n curCSSLeft = fn.css(element, 'left');\n calculatePosition = (position === 'absolute' || position === 'fixed') && \n (curCSSTop + curCSSLeft).indexOf('auto') > -1;\n \n // Need to be able to calculate position if either\n // top or left is auto and position is either absolute or fixed\n if (calculatePosition) {\n curPosition = fn.position(element);\n curTop = curPosition.top;\n curLeft = curPosition.left;\n } else {\n curTop = parseFloat(curCSSTop) || 0;\n curLeft = parseFloat(curCSSLeft) || 0;\n }\n \n if (angular.isFunction(options)) {\n options = options.call(element, i, curOffset);\n }\n \n if (options.top !== null ) {\n props.top = (options.top - curOffset.top) + curTop;\n }\n if ( options.left !== null ) {\n props.left = (options.left - curOffset.left) + curLeft;\n }\n\n if ('using' in options) {\n options.using.call(curElem, props);\n } else {\n curElem.css({\n top: props.top + 'px',\n left: props.left + 'px'\n });\n }\n };\n\n /**\n * Provides read-only equivalent of jQuery's position function\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.position = function(element) {\n\n var offsetParentRect = {top: 0, left: 0},\n offsetParentElement,\n offset;\n\n // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n if (fn.css(element, 'position') === 'fixed') {\n\n // We assume that getBoundingClientRect is available when computed position is fixed\n offset = element.getBoundingClientRect();\n\n } else {\n\n // Get *real* offsetParentElement\n offsetParentElement = offsetParent(element);\n\n // Get correct offsets\n offset = fn.offset(element);\n if (!nodeName(offsetParentElement, 'html')) {\n offsetParentRect = fn.offset(offsetParentElement);\n }\n\n // Add offsetParent borders\n offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);\n offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);\n }\n\n // Subtract parent offsets and element margins\n return {\n width: element.offsetWidth,\n height: element.offsetHeight,\n top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),\n left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)\n };\n\n };\n\n /**\n * Returns the closest, non-statically positioned offsetParent of a given element\n * @required-by fn.position\n * @param element\n */\n var offsetParent = function offsetParentElement(element) {\n var docElement = element.ownerDocument;\n var offsetParent = element.offsetParent || docElement;\n if(nodeName(offsetParent, '#document')) return docElement.documentElement;\n while(offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {\n offsetParent = offsetParent.offsetParent;\n }\n return offsetParent || docElement.documentElement;\n };\n\n /**\n * Provides equivalent of jQuery's height function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/height/\n * @param element\n * @param outer\n */\n fn.height = function(element, outer) {\n var value = element.offsetHeight;\n if(outer) {\n value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);\n } else {\n value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);\n }\n return value;\n };\n\n /**\n * Provides equivalent of jQuery's width function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/width/\n * @param element\n * @param outer\n */\n fn.width = function(element, outer) {\n var value = element.offsetWidth;\n if(outer) {\n value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);\n } else {\n value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);\n }\n return value;\n };\n\n return fn;\n\n });\n\n// Source: helpers/parse-options.js\nangular.module('mgcrea.ngStrap.helpers.parseOptions', [])\n\n .provider('$parseOptions', function() {\n\n var defaults = this.defaults = {\n regexp: /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w]*)|(?:\\(\\s*([\\$\\w][\\$\\w]*)\\s*,\\s*([\\$\\w][\\$\\w]*)\\s*\\)))\\s+in\\s+(.*?)(?:\\s+track\\s+by\\s+(.*?))?$/\n };\n\n this.$get = function($parse, $q) {\n\n function ParseOptionsFactory(attr, config) {\n\n var $parseOptions = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n $parseOptions.$values = [];\n\n // Private vars\n var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;\n\n $parseOptions.init = function() {\n $parseOptions.$match = match = attr.match(options.regexp);\n displayFn = $parse(match[2] || match[1]),\n valueName = match[4] || match[6],\n keyName = match[5],\n groupByFn = $parse(match[3] || ''),\n valueFn = $parse(match[2] ? match[1] : valueName),\n valuesFn = $parse(match[7]);\n };\n\n $parseOptions.valuesFn = function(scope, controller) {\n return $q.when(valuesFn(scope, controller))\n .then(function(values) {\n $parseOptions.$values = values ? parseValues(values, scope) : {};\n return $parseOptions.$values;\n });\n };\n\n $parseOptions.displayValue = function(modelValue) {\n var scope = {};\n scope[valueName] = modelValue;\n return displayFn(scope);\n };\n\n // Private functions\n\n function parseValues(values, scope) {\n return values.map(function(match, index) {\n var locals = {}, label, value;\n locals[valueName] = match;\n label = displayFn(scope, locals);\n value = valueFn(scope, locals);\n return {label: label, value: value, index: index};\n });\n }\n\n $parseOptions.init();\n return $parseOptions;\n\n }\n\n return ParseOptionsFactory;\n\n };\n\n });\n\n// Source: helpers/raf.js\n(angular.version.minor < 3 && angular.version.dot < 14) && angular.module('ng')\n\n.factory('$$rAF', function($window, $timeout) {\n\n var requestAnimationFrame = $window.requestAnimationFrame ||\n $window.webkitRequestAnimationFrame ||\n $window.mozRequestAnimationFrame;\n\n var cancelAnimationFrame = $window.cancelAnimationFrame ||\n $window.webkitCancelAnimationFrame ||\n $window.mozCancelAnimationFrame ||\n $window.webkitCancelRequestAnimationFrame;\n\n var rafSupported = !!requestAnimationFrame;\n var raf = rafSupported ?\n function(fn) {\n var id = requestAnimationFrame(fn);\n return function() {\n cancelAnimationFrame(id);\n };\n } :\n function(fn) {\n var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n return function() {\n $timeout.cancel(timer);\n };\n };\n\n raf.supported = rafSupported;\n\n return raf;\n\n});\n\n// .factory('$$animateReflow', function($$rAF, $document) {\n\n// var bodyEl = $document[0].body;\n\n// return function(fn) {\n// //the returned function acts as the cancellation function\n// return $$rAF(function() {\n// //the line below will force the browser to perform a repaint\n// //so that all the animated elements within the animation frame\n// //will be properly updated and drawn on screen. This is\n// //required to perform multi-class CSS based animations with\n// //Firefox. DO NOT REMOVE THIS LINE.\n// var a = bodyEl.offsetWidth + 1;\n// fn();\n// });\n// };\n\n// });\n\n// Source: modal/modal.js\nangular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$modal', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n backdropAnimation: 'am-fade',\n prefixClass: 'modal',\n prefixEvent: 'modal',\n placement: 'top',\n template: 'modal/modal.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {\n\n var forEach = angular.forEach;\n var trim = String.prototype.trim;\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n var bodyElement = angular.element($window.document.body);\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n\n function ModalFactory(config) {\n\n var $modal = {};\n\n // Common vars\n var options = $modal.$options = angular.extend({}, defaults, config);\n $modal.$promise = fetchTemplate(options.template);\n var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(!options.element && !options.container) {\n options.container = 'body';\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $modal.$id = options.id || options.element && options.element.attr('id') || '';\n\n // Support scope as string options\n forEach(['title', 'content'], function(key) {\n if(options[key]) scope[key] = $sce.trustAsHtml(options[key]);\n });\n\n // Provide scope helpers\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $modal.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $modal.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $modal.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $modal.$isShown = scope.$isShown = false;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $modal.$promise = $modal.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);\n // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n if(!config.template) contentEl.next().remove();\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize modal\n var modalLinker, modalElement;\n var backdropElement = angular.element('
');\n backdropElement.css({position:'fixed', top:'0px', left:'0px', bottom:'0px', right:'0px', 'z-index': 1038});\n $modal.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n modalLinker = $compile(template);\n $modal.init();\n });\n\n $modal.init = function() {\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n $modal.show();\n });\n }\n\n };\n\n $modal.destroy = function() {\n\n // Remove element\n if(modalElement) {\n modalElement.remove();\n modalElement = null;\n }\n if(backdropElement) {\n backdropElement.remove();\n backdropElement = null;\n }\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $modal.show = function() {\n if($modal.$isShown) return;\n\n var parent, after;\n if(angular.isElement(options.container)) {\n parent = options.container;\n after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;\n } else {\n if (options.container) {\n parent = findElement(options.container);\n after = parent[0] && parent[0].lastChild ? angular.element(parent[0].lastChild) : null;\n } else {\n parent = null;\n after = options.element;\n }\n }\n\n // Fetch a cloned element linked from template\n modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\n\n if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n return;\n }\n\n // Set the initial positioning.\n modalElement.css({display: 'block'}).addClass(options.placement);\n\n // Options: animation\n if(options.animation) {\n if(options.backdrop) {\n backdropElement.addClass(options.backdropAnimation);\n }\n modalElement.addClass(options.animation);\n }\n\n if(options.backdrop) {\n $animate.enter(backdropElement, bodyElement, null);\n }\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.enter(modalElement, parent, after, enterAnimateCallback);\n if(promise && promise.then) promise.then(enterAnimateCallback);\n\n $modal.$isShown = scope.$isShown = true;\n safeDigest(scope);\n // Focus once the enter-animation has started\n // Weird PhantomJS bug hack\n var el = modalElement[0];\n requestAnimationFrame(function() {\n el.focus();\n });\n\n bodyElement.addClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n }\n\n // Bind events\n if(options.backdrop) {\n modalElement.on('click', hideOnBackdropClick);\n backdropElement.on('click', hideOnBackdropClick);\n backdropElement.on('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.on('keyup', $modal.$onKeyUp);\n }\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $modal);\n }\n\n $modal.hide = function() {\n if(!$modal.$isShown) return;\n\n if(scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {\n return;\n }\n var promise = $animate.leave(modalElement, leaveAnimateCallback);\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n if(options.backdrop) {\n $animate.leave(backdropElement);\n }\n $modal.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.backdrop) {\n modalElement.off('click', hideOnBackdropClick);\n backdropElement.off('click', hideOnBackdropClick);\n backdropElement.off('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.off('keyup', $modal.$onKeyUp);\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $modal);\n bodyElement.removeClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n }\n }\n\n $modal.toggle = function() {\n\n $modal.$isShown ? $modal.hide() : $modal.show();\n\n };\n\n $modal.focus = function() {\n modalElement[0].focus();\n };\n\n // Protected methods\n\n $modal.$onKeyUp = function(evt) {\n\n if (evt.which === 27 && $modal.$isShown) {\n $modal.hide();\n evt.stopPropagation();\n }\n\n };\n\n // Private methods\n\n function hideOnBackdropClick(evt) {\n if(evt.target !== evt.currentTarget) return;\n options.backdrop === 'static' ? $modal.focus() : $modal.hide();\n }\n\n function preventEventDefault(evt) {\n evt.preventDefault();\n }\n\n return $modal;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return ModalFactory;\n\n };\n\n })\n\n .directive('bsModal', function($window, $sce, $modal) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsModal && scope.$watch(attr.bsModal, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize modal\n var modal = $modal(options);\n\n // Trigger\n element.on(attr.trigger || 'click', modal.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (modal) modal.destroy();\n options = null;\n modal = null;\n });\n\n }\n };\n\n });\n\n// Source: navbar/navbar.js\nangular.module('mgcrea.ngStrap.navbar', [])\n\n .provider('$navbar', function() {\n\n var defaults = this.defaults = {\n activeClass: 'active',\n routeAttr: 'data-match-route',\n strict: false\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsNavbar', function($window, $location, $navbar) {\n\n var defaults = $navbar.defaults;\n\n return {\n restrict: 'A',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = angular.copy(defaults);\n angular.forEach(Object.keys(defaults), function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Watch for the $location\n scope.$watch(function() {\n\n return $location.path();\n\n }, function(newValue, oldValue) {\n\n var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');\n\n angular.forEach(liElements, function(li) {\n\n var liElement = angular.element(li);\n var pattern = liElement.attr(options.routeAttr).replace('/', '\\\\/');\n if(options.strict) {\n pattern = '^' + pattern + '$';\n }\n var regexp = new RegExp(pattern, 'i');\n\n if(regexp.test(newValue)) {\n liElement.addClass(options.activeClass);\n } else {\n liElement.removeClass(options.activeClass);\n }\n\n });\n\n });\n\n }\n\n };\n\n });\n\n// Source: popover/popover.js\nangular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$popover', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n // uncommenting the next two lines will break backwards compatability\n // prefixClass: 'popover',\n // prefixEvent: 'popover',\n container: false,\n target: false,\n placement: 'right',\n template: 'popover/popover.tpl.html',\n contentTemplate: false,\n trigger: 'click',\n keyboard: true,\n html: false,\n title: '',\n content: '',\n delay: 0,\n autoClose: false\n };\n\n this.$get = function($tooltip) {\n\n function PopoverFactory(element, config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n var $popover = $tooltip(element, options);\n\n // Support scope as string options [/*title, */content]\n if(options.content) {\n $popover.$scope.content = options.content;\n }\n\n return $popover;\n\n }\n\n return PopoverFactory;\n\n };\n\n })\n\n .directive('bsPopover', function($window, $sce, $popover) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'customClass', 'autoClose', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoClose'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n });\n });\n\n // Support scope as an object\n attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);\n newValue === true ? popover.show() : popover.hide();\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n popover.setViewport(newValue);\n });\n\n // Initialize popover\n var popover = $popover(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (popover) popover.destroy();\n options = null;\n popover = null;\n });\n\n }\n };\n\n });\n\n// Source: scrollspy/scrollspy.js\nangular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', 'mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$scrollspy', function() {\n\n // Pool of registered spies\n var spies = this.$$spies = {};\n\n var defaults = this.defaults = {\n debounce: 150,\n throttle: 100,\n offset: 100\n };\n\n this.$get = function($window, $document, $rootScope, dimensions, debounce, throttle) {\n\n var windowEl = angular.element($window);\n var docEl = angular.element($document.prop('documentElement'));\n var bodyEl = angular.element($window.document.body);\n\n // Helper functions\n\n function nodeName(element, name) {\n return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();\n }\n\n function ScrollSpyFactory(config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n if(!options.element) options.element = bodyEl;\n var isWindowSpy = nodeName(options.element, 'body');\n var scrollEl = isWindowSpy ? windowEl : options.element;\n var scrollId = isWindowSpy ? 'window' : options.id;\n\n // Use existing spy\n if(spies[scrollId]) {\n spies[scrollId].$$count++;\n return spies[scrollId];\n }\n\n var $scrollspy = {};\n\n // Private vars\n var unbindViewContentLoaded, unbindIncludeContentLoaded;\n var trackedElements = $scrollspy.$trackedElements = [];\n var sortedElements = [];\n var activeTarget;\n var debouncedCheckPosition;\n var throttledCheckPosition;\n var debouncedCheckOffsets;\n var viewportHeight;\n var scrollTop;\n\n $scrollspy.init = function() {\n\n // Setup internal ref counter\n this.$$count = 1;\n\n // Bind events\n debouncedCheckPosition = debounce(this.checkPosition, options.debounce);\n throttledCheckPosition = throttle(this.checkPosition, options.throttle);\n scrollEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', debouncedCheckPosition);\n scrollEl.on('scroll', throttledCheckPosition);\n\n debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);\n unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);\n unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);\n debouncedCheckOffsets();\n\n // Register spy for reuse\n if(scrollId) {\n spies[scrollId] = $scrollspy;\n }\n\n };\n\n $scrollspy.destroy = function() {\n\n // Check internal ref counter\n this.$$count--;\n if(this.$$count > 0) {\n return;\n }\n\n // Unbind events\n scrollEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', debouncedCheckPosition);\n scrollEl.off('scroll', throttledCheckPosition);\n unbindViewContentLoaded();\n unbindIncludeContentLoaded();\n if (scrollId) {\n delete spies[scrollId];\n }\n };\n\n $scrollspy.checkPosition = function() {\n\n // Not ready yet\n if(!sortedElements.length) return;\n\n // Calculate the scroll position\n scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;\n\n // Calculate the viewport height for use by the components\n viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));\n\n // Activate first element if scroll is smaller\n if(scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {\n return $scrollspy.$activateElement(sortedElements[0]);\n }\n\n // Activate proper element\n for (var i = sortedElements.length; i--;) {\n if(angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) continue;\n if(activeTarget === sortedElements[i].target) continue;\n if(scrollTop < sortedElements[i].offsetTop) continue;\n if(sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) continue;\n return $scrollspy.$activateElement(sortedElements[i]);\n }\n\n };\n\n $scrollspy.checkPositionWithEventLoop = function() {\n // IE 9 throws an error if we use 'this' instead of '$scrollspy'\n // in this setTimeout call\n setTimeout($scrollspy.checkPosition, 1);\n };\n\n // Protected methods\n\n $scrollspy.$activateElement = function(element) {\n if(activeTarget) {\n var activeElement = $scrollspy.$getTrackedElement(activeTarget);\n if(activeElement) {\n activeElement.source.removeClass('active');\n if(nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {\n activeElement.source.parent().parent().removeClass('active');\n }\n }\n }\n activeTarget = element.target;\n element.source.addClass('active');\n if(nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {\n element.source.parent().parent().addClass('active');\n }\n };\n\n $scrollspy.$getTrackedElement = function(target) {\n return trackedElements.filter(function(obj) {\n return obj.target === target;\n })[0];\n };\n\n // Track offsets behavior\n\n $scrollspy.checkOffsets = function() {\n\n angular.forEach(trackedElements, function(trackedElement) {\n var targetElement = document.querySelector(trackedElement.target);\n trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;\n if(options.offset && trackedElement.offsetTop !== null) trackedElement.offsetTop -= options.offset * 1;\n });\n\n sortedElements = trackedElements\n .filter(function(el) {\n return el.offsetTop !== null;\n })\n .sort(function(a, b) {\n return a.offsetTop - b.offsetTop;\n });\n\n debouncedCheckPosition();\n\n };\n\n $scrollspy.trackElement = function(target, source) {\n trackedElements.push({target: target, source: source});\n };\n\n $scrollspy.untrackElement = function(target, source) {\n var toDelete;\n for (var i = trackedElements.length; i--;) {\n if(trackedElements[i].target === target && trackedElements[i].source === source) {\n toDelete = i;\n break;\n }\n }\n trackedElements = trackedElements.splice(toDelete, 1);\n };\n\n $scrollspy.activate = function(i) {\n trackedElements[i].addClass('active');\n };\n\n // Initialize plugin\n\n $scrollspy.init();\n return $scrollspy;\n\n }\n\n return ScrollSpyFactory;\n\n };\n\n })\n\n .directive('bsScrollspy', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'EAC',\n link: function postLink(scope, element, attr) {\n\n var options = {scope: scope};\n angular.forEach(['offset', 'target'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n var scrollspy = $scrollspy(options);\n scrollspy.trackElement(options.target, element);\n\n scope.$on('$destroy', function() {\n if (scrollspy) {\n scrollspy.untrackElement(options.target, element);\n scrollspy.destroy();\n }\n options = null;\n scrollspy = null;\n });\n\n }\n };\n\n })\n\n\n .directive('bsScrollspyList', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'A',\n compile: function postLink(element, attr) {\n var children = element[0].querySelectorAll('li > a[href]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));\n });\n }\n\n };\n\n });\n\n// Source: select/select.js\nangular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$select', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'select',\n prefixEvent: '$select',\n placement: 'bottom-left',\n template: 'select/select.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n multiple: false,\n allNoneButtons: false,\n sort: true,\n caretHtml: ' ',\n placeholder: 'Choose among the following...',\n allText: 'All',\n noneText: 'None',\n maxLength: 3,\n maxLengthHtml: 'selected',\n iconCheckmark: 'glyphicon glyphicon-ok'\n };\n\n this.$get = function($window, $document, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n\n function SelectFactory(element, controller, config) {\n\n var $select = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $select = $tooltip(element, options);\n var scope = $select.$scope;\n\n scope.$matches = [];\n if (options.multiple) {\n scope.$activeIndex = [];\n }\n else {\n scope.$activeIndex = -1;\n }\n scope.$isMultiple = options.multiple;\n scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n scope.$iconCheckmark = options.iconCheckmark;\n scope.$allText = options.allText;\n scope.$noneText = options.noneText;\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $select.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $select.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $select.$isVisible();\n };\n\n scope.$isActive = function(index) {\n return $select.$isActive(index);\n };\n\n scope.$selectAll = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (!scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n scope.$selectNone = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n // Public methods\n\n $select.update = function(matches) {\n scope.$matches = matches;\n $select.$updateActiveIndex();\n };\n\n $select.activate = function(index) {\n if(options.multiple) {\n $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);\n if(options.sort) scope.$activeIndex.sort();\n } else {\n scope.$activeIndex = index;\n }\n return scope.$activeIndex;\n };\n\n $select.select = function(index) {\n var value = scope.$matches[index].value;\n scope.$apply(function() {\n $select.activate(index);\n if(options.multiple) {\n controller.$setViewValue(scope.$activeIndex.map(function(index) {\n return scope.$matches[index].value;\n }));\n } else {\n controller.$setViewValue(value);\n // Hide if single select\n $select.hide();\n }\n });\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $select);\n };\n\n // Protected methods\n\n $select.$updateActiveIndex = function() {\n if(controller.$modelValue && scope.$matches.length) {\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n scope.$activeIndex = controller.$modelValue.map(function(value) {\n return $select.$getIndex(value);\n });\n } else {\n scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n }\n } else if(scope.$activeIndex >= scope.$matches.length) {\n scope.$activeIndex = options.multiple ? [] : 0;\n }\n };\n\n $select.$isVisible = function() {\n if(!options.minLength || !controller) {\n return scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && controller.$viewValue.length >= options.minLength;\n };\n\n $select.$isActive = function(index) {\n if(options.multiple) {\n return scope.$activeIndex.indexOf(index) !== -1;\n } else {\n return scope.$activeIndex === index;\n }\n };\n\n $select.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $select.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n targetEl.triggerHandler('click');\n }\n };\n\n $select.$onKeyDown = function(evt) {\n if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // release focus on tab\n if (options.multiple && evt.keyCode === 9) {\n return $select.hide();\n }\n\n // Select with enter\n if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n return $select.select(scope.$activeIndex);\n }\n\n if (!options.multiple) {\n // Navigate with keyboard\n if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 38 && scope.$activeIndex < 0) scope.$activeIndex = scope.$matches.length - 1;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n }\n };\n\n // Overrides\n\n var _show = $select.show;\n $select.show = function() {\n _show();\n if(options.multiple) {\n $select.$element.addClass('select-multiple');\n }\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $select.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $select.hide;\n $select.hide = function() {\n if(!options.multiple && !controller.$modelValue) {\n scope.$activeIndex = -1;\n }\n $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $select.$onKeyDown);\n }\n _hide(true);\n };\n\n return $select;\n\n }\n\n SelectFactory.defaults = defaults;\n return SelectFactory;\n\n };\n\n })\n\n .directive('bsSelect', function($window, $parse, $q, $select, $parseOptions) {\n\n var defaults = $select.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, placeholder: defaults.placeholder};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'placeholder', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id', 'sort', 'caretHtml', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'allNoneButtons', 'sort'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Only parse data-multiple. Angular sets existence attributes to true (multiple/required/etc), they apply this\n // to data-multiple as well for some reason, so we'll parse this ourselves and disregard multiple\n var dataMultiple = element.attr('data-multiple');\n if(angular.isDefined(dataMultiple)) {\n if(falseValueRegExp.test(dataMultiple))\n options.multiple = false;\n else\n options.multiple = dataMultiple;\n }\n\n // Add support for select markup\n if(element[0].nodeName.toLowerCase() === 'select') {\n var inputEl = element;\n inputEl.css('display', 'none');\n element = angular.element('');\n inputEl.after(element);\n }\n\n // Build proper bsOptions\n var parsedOptions = $parseOptions(attr.bsOptions);\n\n // Initialize select\n var select = $select(element, controller, options);\n\n // Watch bsOptions values before filtering for changes\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n scope.$watchCollection(watchedOptions, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n select.update(values);\n controller.$render();\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n select.$updateActiveIndex();\n controller.$render();\n }, true);\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var selected, index;\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n selected = controller.$modelValue.map(function(value) {\n index = select.$getIndex(value);\n return angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }).filter(angular.isDefined);\n if(selected.length > (options.maxLength || defaults.maxLength)) {\n selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml);\n } else {\n selected = selected.join(', ');\n }\n } else {\n index = select.$getIndex(controller.$modelValue);\n selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }\n element.html((selected ? selected : options.placeholder) + (options.caretHtml ? options.caretHtml : defaults.caretHtml));\n };\n\n if(options.multiple){\n controller.$isEmpty = function(value){\n return !value || value.length === 0;\n };\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (select) select.destroy();\n options = null;\n select = null;\n });\n\n }\n };\n\n });\n\n// Source: timepicker/timepicker.js\nangular.module('mgcrea.ngStrap.timepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$timepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'timepicker',\n prefixClass: 'timepicker',\n placement: 'bottom-left',\n template: 'timepicker/timepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: true,\n timeType: 'date',\n timeFormat: 'shortTime',\n timezone: null,\n modelTimeFormat: null,\n autoclose: false,\n minTime: -Infinity,\n maxTime: +Infinity,\n length: 5,\n hourStep: 1,\n minuteStep: 5,\n secondStep: 5,\n roundDisplay: false,\n iconUp: 'glyphicon glyphicon-chevron-up',\n iconDown: 'glyphicon glyphicon-chevron-down',\n arrowBehavior: 'pager'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function timepickerFactory(element, controller, config) {\n\n var $timepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $timepicker.$options;\n var scope = $timepicker.$scope;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n function floorMinutes(time)\n {\n // coeff used to floor current time to nearest minuteStep interval\n var coeff = 1000 * 60 * options.minuteStep;\n return new Date(Math.floor(time.getTime() / coeff) * coeff);\n }\n\n // View vars\n\n var selectedIndex = 0;\n var defaultDate = options.roundDisplay ? floorMinutes(new Date()) : new Date();\n var startDate = controller.$dateValue || defaultDate;\n var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n var hoursFormat = $dateFormatter.hoursFormat(format),\n timeSeparator = $dateFormatter.timeSeparator(format),\n minutesFormat = $dateFormatter.minutesFormat(format),\n secondsFormat = $dateFormatter.secondsFormat(format),\n showSeconds = $dateFormatter.showSeconds(format),\n showAM = $dateFormatter.showAM(format);\n\n scope.$iconUp = options.iconUp;\n scope.$iconDown = options.iconDown;\n\n // Scope methods\n\n scope.$select = function(date, index) {\n $timepicker.select(date, index);\n };\n scope.$moveIndex = function(value, index) {\n $timepicker.$moveIndex(value, index);\n };\n scope.$switchMeridian = function(date) {\n $timepicker.switchMeridian(date);\n };\n\n // Public methods\n\n $timepicker.update = function(date) {\n // console.warn('$timepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $timepicker.$date = date;\n angular.extend(viewDate, {hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds(), millisecond: date.getMilliseconds()});\n $timepicker.$build();\n } else if(!$timepicker.$isBuilt) {\n $timepicker.$build();\n }\n };\n\n $timepicker.select = function(date, index, keep) {\n // console.warn('$timepicker.select', date, scope.$mode);\n if(!controller.$dateValue || isNaN(controller.$dateValue.getTime())) controller.$dateValue = new Date(1970, 0, 1);\n if(!angular.isDate(date)) date = new Date(date);\n if(index === 0) controller.$dateValue.setHours(date.getHours());\n else if(index === 1) controller.$dateValue.setMinutes(date.getMinutes());\n else if(index === 2) controller.$dateValue.setSeconds(date.getSeconds());\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $timepicker.hide(true); });\n }\n };\n\n $timepicker.switchMeridian = function(date) {\n if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) {\n return;\n }\n var hours = (date || controller.$dateValue).getHours();\n controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12);\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n };\n\n // Protected methods\n\n $timepicker.$build = function() {\n // console.warn('$timepicker.$build() viewDate=%o', viewDate);\n var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n var hours = [], hour;\n for(i = 0; i < options.length; i++) {\n hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);\n hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});\n }\n var minutes = [], minute;\n for(i = 0; i < options.length; i++) {\n minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);\n minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n }\n var seconds = [], second;\n for(i = 0; i < options.length; i++) {\n second = new Date(1970, 0, 1, 0, 0, viewDate.second - (midIndex - i) * options.secondStep);\n seconds.push({date: second, label: formatDate(second, secondsFormat), selected: $timepicker.$date && $timepicker.$isSelected(second, 2), disabled: $timepicker.$isDisabled(second, 2)});\n }\n\n var rows = [];\n for(i = 0; i < options.length; i++) {\n if (showSeconds) {\n rows.push([hours[i], minutes[i], seconds[i]]);\n } else {\n rows.push([hours[i], minutes[i]]);\n }\n }\n scope.rows = rows;\n scope.showSeconds = showSeconds;\n scope.showAM = showAM;\n scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n scope.timeSeparator = timeSeparator;\n $timepicker.$isBuilt = true;\n };\n\n $timepicker.$isSelected = function(date, index) {\n if(!$timepicker.$date) return false;\n else if(index === 0) {\n return date.getHours() === $timepicker.$date.getHours();\n } else if(index === 1) {\n return date.getMinutes() === $timepicker.$date.getMinutes();\n } else if(index === 2) {\n return date.getSeconds() === $timepicker.$date.getSeconds();\n }\n };\n\n $timepicker.$isDisabled = function(date, index) {\n var selectedTime;\n if(index === 0) {\n selectedTime = date.getTime() + viewDate.minute * 6e4 + viewDate.second * 1e3;\n } else if(index === 1) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.second * 1e3;\n } else if(index === 2) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.minute * 6e4;\n }\n return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1;\n };\n\n scope.$arrowAction = function (value, index) {\n if (options.arrowBehavior === 'picker') {\n $timepicker.$setTimeByStep(value,index);\n } else {\n $timepicker.$moveIndex(value,index);\n }\n };\n\n $timepicker.$setTimeByStep = function(value, index) {\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n if (index === 0) {\n newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n }\n else if (index === 1) {\n newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\n }\n else if (index === 2) {\n newDate.setSeconds(seconds - (parseInt(options.secondStep, 10) * value));\n }\n $timepicker.select(newDate, index, true);\n };\n\n $timepicker.$moveIndex = function(value, index) {\n var targetDate;\n if(index === 0) {\n targetDate = new Date(1970, 0, 1, viewDate.hour + (value * options.length), viewDate.minute, viewDate.second);\n angular.extend(viewDate, {hour: targetDate.getHours()});\n } else if(index === 1) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + (value * options.length * options.minuteStep), viewDate.second);\n angular.extend(viewDate, {minute: targetDate.getMinutes()});\n } else if(index === 2) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute, viewDate.second + (value * options.length * options.secondStep));\n angular.extend(viewDate, {second: targetDate.getSeconds()});\n }\n $timepicker.$build();\n };\n\n $timepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n if(evt.target.nodeName.toLowerCase() !== 'input') evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $timepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Close on enter\n if(evt.keyCode === 13) return $timepicker.hide(true);\n\n // Navigate with keyboard\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n var sepLength = 1;\n var lateralMove = /(37|39)/.test(evt.keyCode);\n var count = 2 + showSeconds * 1 + showAM * 1;\n\n // Navigate indexes (left, right)\n if (lateralMove) {\n if(evt.keyCode === 37) selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1;\n else if(evt.keyCode === 39) selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0;\n }\n\n // Update values (up, down)\n var selectRange = [0, hoursLength];\n var incr = 0;\n if (evt.keyCode === 38) incr = -1;\n if (evt.keyCode === 40) incr = +1;\n var isSeconds = selectedIndex === 2 && showSeconds;\n var isMeridian = selectedIndex === 2 && !showSeconds || selectedIndex === 3 && showSeconds;\n if(selectedIndex === 0) {\n newDate.setHours(hours + incr*parseInt(options.hourStep, 10));\n // re-calculate hours length because we have changed hours value\n hoursLength = formatDate(newDate, hoursFormat).length;\n selectRange = [0, hoursLength];\n } else if(selectedIndex === 1) {\n newDate.setMinutes(minutes + incr*parseInt(options.minuteStep, 10));\n // re-calculate minutes length because we have changes minutes value\n minutesLength = formatDate(newDate, minutesFormat).length;\n selectRange = [hoursLength + sepLength, minutesLength];\n } else if(isSeconds) {\n newDate.setSeconds(seconds + incr*parseInt(options.secondStep, 10));\n // re-calculate seconds length because we have changes seconds value\n secondsLength = formatDate(newDate, secondsFormat).length;\n selectRange = [hoursLength + sepLength + minutesLength + sepLength, secondsLength];\n } else if(isMeridian) {\n if(!lateralMove) $timepicker.switchMeridian();\n selectRange = [hoursLength + sepLength + minutesLength + sepLength + (secondsLength + sepLength)*showSeconds, 2];\n }\n $timepicker.select(newDate, selectedIndex, true);\n createSelection(selectRange[0], selectRange[1]);\n parentScope.$digest();\n };\n\n // Private\n\n function createSelection(start, length) {\n var end = start + length;\n if(element[0].createTextRange) {\n var selRange = element[0].createTextRange();\n selRange.collapse(true);\n selRange.moveStart('character', start);\n selRange.moveEnd('character', end);\n selRange.select();\n } else if(element[0].setSelectionRange) {\n element[0].setSelectionRange(start, end);\n } else if(angular.isUndefined(element[0].selectionStart)) {\n element[0].selectionStart = start;\n element[0].selectionEnd = end;\n }\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $timepicker.init;\n $timepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'time');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $timepicker.destroy;\n $timepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $timepicker.show;\n $timepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $timepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $timepicker.hide;\n $timepicker.hide = function(blur) {\n if(!$timepicker.$isShown) return;\n $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $timepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $timepicker;\n\n }\n\n timepickerFactory.defaults = defaults;\n return timepickerFactory;\n\n };\n\n })\n\n\n .directive('bsTimepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n var defaults = $timepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'timeType', 'timeFormat', 'timezone', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'secondStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'roundDisplay', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative', 'roundDisplay'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!timepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(timepicker),?/i);\n newValue === true ? timepicker.show() : timepicker.hide();\n });\n\n // Initialize timepicker\n if(isNative && (options.useNative || defaults.useNative)) options.timeFormat = 'HH:mm';\n var timepicker = $timepicker(element, controller, options);\n options = timepicker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n // Initialize parser\n var dateParser = $dateParser({format: options.timeFormat, lang: lang});\n\n // Observe attributes for changes\n angular.forEach(['minTime', 'maxTime'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n !isNaN(timepicker.$options[key]) && timepicker.$build();\n validateAgainstMinMaxTime(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue);\n timepicker.update(controller.$dateValue);\n }, true);\n\n function validateAgainstMinMaxTime(parsedTime) {\n if (!angular.isDate(parsedTime)) return;\n var isMinValid = isNaN(options.minTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) >= options.minTime;\n var isMaxValid = isNaN(options.maxTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) <= options.maxTime;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(!isValid) {\n return;\n }\n controller.$dateValue = parsedTime;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n controller.$setValidity('date', true);\n return null;\n }\n var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedTime || isNaN(parsedTime.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxTime(parsedTime);\n }\n\n if(options.timeType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedTime, options.timezone, true);\n return formatDate(date, options.modelTimeFormat || options.timeFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.timeType === 'number') {\n return date.getTime();\n } else if(options.timeType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.timeType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.timeType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelTimeFormat);\n } else if(options.timeType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5);\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getTimeFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getTimeFormattedString());\n };\n\n function getTimeFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (timepicker) timepicker.destroy();\n options = null;\n timepicker = null;\n });\n\n }\n };\n\n });\n\n// Source: tab/tab.js\nangular.module('mgcrea.ngStrap.tab', [])\n\n .provider('$tab', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n template: 'tab/tab.tpl.html',\n navClass: 'nav-tabs',\n activeClass: 'active'\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'navClass', 'activeClass'], function(key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // Publish options on scope\n $scope.$navClass = self.$options.navClass;\n $scope.$activeClass = self.$options.activeClass;\n\n self.$panes = $scope.$panes = [];\n\n // Please use $activePaneChangeListeners if you use `bsActivePane`\n // Because we removed `ngModel` as default, we rename viewChangeListeners to\n // activePaneChangeListeners to make more sense.\n self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var activeIndex = self.$panes.$active;\n\n // remove pane from $panes array\n self.$panes.splice(index, 1);\n\n if (index < activeIndex) {\n // we removed a pane before the active pane, so we need to\n // decrement the active pane index\n activeIndex--;\n }\n else if (index === activeIndex && activeIndex === self.$panes.length) {\n // we remove the active pane and it was the one at the end,\n // so select the previous one\n activeIndex--;\n }\n self.$setActive(activeIndex);\n };\n\n self.$panes.$active = 0;\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$activePaneChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n };\n\n this.$get = function() {\n var $tab = {};\n $tab.defaults = defaults;\n $tab.controller = controller;\n return $tab;\n };\n\n })\n\n .directive('bsTabs', function($window, $animate, $tab, $parse) {\n\n var defaults = $tab.defaults;\n\n return {\n require: ['?ngModel', 'bsTabs'],\n transclude: true,\n scope: true,\n controller: ['$scope', '$element', '$attrs', $tab.controller],\n templateUrl: function(element, attr) {\n return attr.template || defaults.template;\n },\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // 'ngModel' does interfere with form validation\n // and status, use `bsActivePane` instead to avoid it\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n bsTabsCtrl.$setActive(modelValue * 1);\n return modelValue;\n });\n\n }\n\n if (attrs.bsActivePane) {\n // adapted from angularjs ngModelController bindings\n // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n // Update bsActivePane value with change\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n });\n\n // watch bsActivePane for value changes\n scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n bsTabsCtrl.$setActive(newValue * 1);\n }, true);\n }\n }\n };\n\n })\n\n .directive('bsPane', function($window, $animate, $sce) {\n\n return {\n require: ['^?ngModel', '^bsTabs'],\n scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // Add base class\n element.addClass('tab-pane');\n\n // Observe title attribute for change\n attrs.$observe('title', function(newValue, oldValue) {\n scope.title = $sce.trustAsHtml(newValue);\n });\n\n // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\n }\n\n attrs.$observe('disabled', function(newValue, oldValue) {\n scope.disabled = scope.$eval(newValue);\n });\n\n // Push pane to parent bsTabs controller\n bsTabsCtrl.$push(scope);\n\n // remove pane from tab controller when pane is destroyed\n scope.$on('$destroy', function() {\n bsTabsCtrl.$remove(scope);\n });\n\n function render() {\n var index = bsTabsCtrl.$panes.indexOf(scope);\n var active = bsTabsCtrl.$panes.$active;\n $animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n\n// Source: tooltip/tooltip.js\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$tooltip', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n prefixClass: 'tooltip',\n prefixEvent: 'tooltip',\n container: false,\n target: false,\n placement: 'top',\n template: 'tooltip/tooltip.tpl.html',\n contentTemplate: false,\n trigger: 'hover focus',\n keyboard: false,\n html: false,\n show: false,\n title: '',\n type: '',\n delay: 0,\n autoClose: false,\n bsEnabled: true,\n viewport: {\n selector: 'body',\n padding: 0\n }\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n var trim = String.prototype.trim;\n var isTouch = 'createTouch' in $window.document;\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n var $body = angular.element($window.document);\n\n function TooltipFactory(element, config) {\n\n var $tooltip = {};\n\n // Common vars\n var nodeName = element[0].nodeName.toLowerCase();\n var options = $tooltip.$options = angular.extend({}, defaults, config);\n $tooltip.$promise = fetchTemplate(options.template);\n var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(options.delay && angular.isString(options.delay)) {\n var split = options.delay.split(',').map(parseFloat);\n options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $tooltip.$id = options.id || element.attr('id') || '';\n\n // Support scope as string options\n if(options.title) {\n scope.title = $sce.trustAsHtml(options.title);\n }\n\n // Provide scope helpers\n scope.$setEnabled = function(isEnabled) {\n scope.$$postDigest(function() {\n $tooltip.setEnabled(isEnabled);\n });\n };\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $tooltip.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $tooltip.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $tooltip.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $tooltip.$isShown = scope.$isShown = false;\n\n // Private vars\n var timeout, hoverState;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $tooltip.$promise = $tooltip.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]);\n if(!contentEl.length) contentEl = findElement('[ng-bind=\"title\"]', templateEl[0]);\n contentEl.removeAttr('ng-bind').html(contentTemplate);\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize tooltip\n var tipLinker, tipElement, tipTemplate, tipContainer, tipScope;\n $tooltip.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n tipTemplate = template;\n tipLinker = $compile(template);\n $tooltip.init();\n });\n\n $tooltip.init = function() {\n\n // Options: delay\n if (options.delay && angular.isNumber(options.delay)) {\n options.delay = {\n show: options.delay,\n hide: options.delay\n };\n }\n\n // Replace trigger on touch devices ?\n // if(isTouch && options.trigger === defaults.trigger) {\n // options.trigger.replace(/hover/g, 'click');\n // }\n\n // Options : container\n if(options.container === 'self') {\n tipContainer = element;\n } else if(angular.isElement(options.container)) {\n tipContainer = options.container;\n } else if(options.container) {\n tipContainer = findElement(options.container);\n }\n\n // Options: trigger\n bindTriggerEvents();\n\n // Options: target\n if(options.target) {\n options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n }\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n options.trigger === 'focus' ? element[0].focus() : $tooltip.show();\n });\n }\n\n };\n\n $tooltip.destroy = function() {\n\n // Unbind events\n unbindTriggerEvents();\n\n // Remove element\n destroyTipElement();\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $tooltip.enter = function() {\n\n clearTimeout(timeout);\n hoverState = 'in';\n if (!options.delay || !options.delay.show) {\n return $tooltip.show();\n }\n\n timeout = setTimeout(function() {\n if (hoverState ==='in') $tooltip.show();\n }, options.delay.show);\n\n };\n\n $tooltip.show = function() {\n if (!options.bsEnabled || $tooltip.$isShown) return;\n\n scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n var parent, after;\n if (options.container) {\n parent = tipContainer;\n if (tipContainer[0].lastChild) {\n after = angular.element(tipContainer[0].lastChild);\n } else {\n after = null;\n }\n } else {\n parent = null;\n after = element;\n }\n\n\n // Hide any existing tipElement\n if(tipElement) destroyTipElement();\n // Fetch a cloned element linked from template\n tipScope = $tooltip.$scope.$new();\n tipElement = $tooltip.$element = tipLinker(tipScope, function(clonedElement, scope) {});\n\n // Set the initial positioning. Make the tooltip invisible\n // so IE doesn't try to focus on it off screen.\n tipElement.css({top: '-9999px', left: '-9999px', right: 'auto', display: 'block', visibility: 'hidden'});\n\n // Options: animation\n if(options.animation) tipElement.addClass(options.animation);\n // Options: type\n if(options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n // Options: custom classes\n if(options.customClass) tipElement.addClass(options.customClass);\n\n // Append the element, without any animations. If we append\n // using $animate.enter, some of the animations cause the placement\n // to be off due to the transforms.\n after ? after.after(tipElement) : parent.prepend(tipElement);\n\n $tooltip.$isShown = scope.$isShown = true;\n safeDigest(scope);\n\n // Now, apply placement\n $tooltip.$applyPlacement();\n\n // Once placed, animate it.\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.enter(tipElement, parent, after, enterAnimateCallback);\n if(promise && promise.then) promise.then(enterAnimateCallback);\n safeDigest(scope);\n\n $$rAF(function () {\n // Once the tooltip is placed and the animation starts, make the tooltip visible\n if(tipElement) tipElement.css({visibility: 'visible'});\n });\n\n // Bind events\n if(options.keyboard) {\n if(options.trigger !== 'focus') {\n $tooltip.focus();\n }\n bindKeyboardEvents();\n }\n\n if(options.autoClose) {\n bindAutoCloseEvents();\n }\n\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $tooltip);\n }\n\n $tooltip.leave = function() {\n\n clearTimeout(timeout);\n hoverState = 'out';\n if (!options.delay || !options.delay.hide) {\n return $tooltip.hide();\n }\n timeout = setTimeout(function () {\n if (hoverState === 'out') {\n $tooltip.hide();\n }\n }, options.delay.hide);\n\n };\n\n var _blur;\n var _tipToHide;\n $tooltip.hide = function(blur) {\n\n if(!$tooltip.$isShown) return;\n scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n\n // store blur value for leaveAnimateCallback to use\n _blur = blur;\n\n // store current tipElement reference to use\n // in leaveAnimateCallback\n _tipToHide = tipElement;\n\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.leave(tipElement, leaveAnimateCallback);\n if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n $tooltip.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.keyboard && tipElement !== null) {\n unbindKeyboardEvents();\n }\n\n if(options.autoClose && tipElement !== null) {\n unbindAutoCloseEvents();\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\n\n // check if current tipElement still references\n // the same element when hide was called\n if (tipElement === _tipToHide) {\n // Allow to blur the input when hidden, like when pressing enter key\n if(_blur && options.trigger === 'focus') {\n return element[0].blur();\n }\n\n // clean up child scopes\n destroyTipElement();\n }\n }\n\n $tooltip.toggle = function() {\n $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter();\n };\n\n $tooltip.focus = function() {\n tipElement[0].focus();\n };\n\n $tooltip.setEnabled = function(isEnabled) {\n options.bsEnabled = isEnabled;\n };\n\n $tooltip.setViewport = function(viewport) {\n options.viewport = viewport;\n };\n\n // Protected methods\n\n $tooltip.$applyPlacement = function() {\n if(!tipElement) return;\n\n // Determine if we're doing an auto or normal placement\n var placement = options.placement,\n autoToken = /\\s?auto?\\s?/i,\n autoPlace = autoToken.test(placement);\n\n if (autoPlace) {\n placement = placement.replace(autoToken, '') || defaults.placement;\n }\n\n // Need to add the position class before we get\n // the offsets\n tipElement.addClass(options.placement);\n\n // Get the position of the target element\n // and the height and width of the tooltip so we can center it.\n var elementPosition = getPosition(),\n tipWidth = tipElement.prop('offsetWidth'),\n tipHeight = tipElement.prop('offsetHeight');\n\n // If we're auto placing, we need to check the positioning\n if (autoPlace) {\n var originalPlacement = placement;\n var container = options.container ? findElement(options.container) : element.parent();\n var containerPosition = getPosition(container);\n\n // Determine if the vertical placement\n if (originalPlacement.indexOf('bottom') >= 0 && elementPosition.bottom + tipHeight > containerPosition.bottom) {\n placement = originalPlacement.replace('bottom', 'top');\n } else if (originalPlacement.indexOf('top') >= 0 && elementPosition.top - tipHeight < containerPosition.top) {\n placement = originalPlacement.replace('top', 'bottom');\n }\n\n // Determine the horizontal placement\n // The exotic placements of left and right are opposite of the standard placements. Their arrows are put on the left/right\n // and flow in the opposite direction of their placement.\n if ((originalPlacement === 'right' || originalPlacement === 'bottom-left' || originalPlacement === 'top-left') &&\n elementPosition.right + tipWidth > containerPosition.width) {\n\n placement = originalPlacement === 'right' ? 'left' : placement.replace('left', 'right');\n } else if ((originalPlacement === 'left' || originalPlacement === 'bottom-right' || originalPlacement === 'top-right') &&\n elementPosition.left - tipWidth < containerPosition.left) {\n\n placement = originalPlacement === 'left' ? 'right' : placement.replace('right', 'left');\n }\n\n tipElement.removeClass(originalPlacement).addClass(placement);\n }\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n applyPlacement(tipPosition, placement);\n };\n\n $tooltip.$onKeyUp = function(evt) {\n if (evt.which === 27 && $tooltip.$isShown) {\n $tooltip.hide();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusKeyUp = function(evt) {\n if (evt.which === 27) {\n element[0].blur();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusElementMouseDown = function(evt) {\n evt.preventDefault();\n evt.stopPropagation();\n // Some browsers do not auto-focus buttons (eg. Safari)\n $tooltip.$isShown ? element[0].blur() : element[0].focus();\n };\n\n // bind/unbind events\n function bindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n angular.forEach(triggers, function(trigger) {\n if(trigger === 'click') {\n element.on('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n });\n }\n\n function unbindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n for (var i = triggers.length; i--;) {\n var trigger = triggers[i];\n if(trigger === 'click') {\n element.off('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n }\n }\n\n function bindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.on('keyup', $tooltip.$onKeyUp);\n } else {\n element.on('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n function unbindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.off('keyup', $tooltip.$onKeyUp);\n } else {\n element.off('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n var _autoCloseEventsBinded = false;\n function bindAutoCloseEvents() {\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // Stop propagation when clicking inside tooltip\n tipElement.on('click', stopEventPropagation);\n\n // Hide when clicking outside tooltip\n $body.on('click', $tooltip.hide);\n\n _autoCloseEventsBinded = true;\n }, 0, false);\n }\n\n function unbindAutoCloseEvents() {\n if (_autoCloseEventsBinded) {\n tipElement.off('click', stopEventPropagation);\n $body.off('click', $tooltip.hide);\n _autoCloseEventsBinded = false;\n }\n }\n\n function stopEventPropagation(event) {\n event.stopPropagation();\n }\n\n // Private methods\n\n function getPosition($element) {\n $element = $element || (options.target || element);\n\n var el = $element[0],\n isBody = el.tagName === 'BODY';\n\n var elRect = el.getBoundingClientRect();\n var rect = {};\n\n // IE8 has issues with angular.extend and using elRect directly.\n // By coping the values of elRect into a new object, we can continue to use extend\n for (var p in elRect) {\n // DO NOT use hasOwnProperty when inspecting the return of getBoundingClientRect.\n rect[p] = elRect[p];\n }\n\n if (rect.width === null) {\n // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n rect = angular.extend({}, rect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });\n }\n var elOffset = isBody ? { top: 0, left: 0 } : dimensions.offset(el),\n scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.prop('scrollTop') || 0 },\n outerDims = isBody ? { width: document.documentElement.clientWidth, height: $window.innerHeight } : null;\n\n return angular.extend({}, rect, scroll, outerDims, elOffset);\n }\n\n function getCalculatedOffset(placement, position, actualWidth, actualHeight) {\n var offset;\n var split = placement.split('-');\n\n switch (split[0]) {\n case 'right':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left + position.width\n };\n break;\n case 'bottom':\n offset = {\n top: position.top + position.height,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n case 'left':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left - actualWidth\n };\n break;\n default:\n offset = {\n top: position.top - actualHeight,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n }\n\n if(!split[1]) {\n return offset;\n }\n\n // Add support for corners @todo css\n if(split[0] === 'top' || split[0] === 'bottom') {\n switch (split[1]) {\n case 'left':\n offset.left = position.left;\n break;\n case 'right':\n offset.left = position.left + position.width - actualWidth;\n }\n } else if(split[0] === 'left' || split[0] === 'right') {\n switch (split[1]) {\n case 'top':\n offset.top = position.top - actualHeight;\n break;\n case 'bottom':\n offset.top = position.top + position.height;\n }\n }\n\n return offset;\n }\n\n function applyPlacement(offset, placement) {\n var tip = tipElement[0],\n width = tip.offsetWidth,\n height = tip.offsetHeight;\n\n // manually read margins because getBoundingClientRect includes difference\n var marginTop = parseInt(dimensions.css(tip, 'margin-top'), 10),\n marginLeft = parseInt(dimensions.css(tip, 'margin-left'), 10);\n\n // we must check for NaN for ie 8/9\n if (isNaN(marginTop)) marginTop = 0;\n if (isNaN(marginLeft)) marginLeft = 0;\n\n offset.top = offset.top + marginTop;\n offset.left = offset.left + marginLeft;\n\n // dimensions setOffset doesn't round pixel values\n // so we use setOffset directly with our own function\n dimensions.setOffset(tip, angular.extend({\n using: function (props) {\n tipElement.css({\n top: Math.round(props.top) + 'px',\n left: Math.round(props.left) + 'px',\n right: ''\n });\n }\n }, offset), 0);\n\n // check to see if placing tip in new offset caused the tip to resize itself\n var actualWidth = tip.offsetWidth,\n actualHeight = tip.offsetHeight;\n\n if (placement === 'top' && actualHeight !== height) {\n offset.top = offset.top + height - actualHeight;\n }\n\n // If it's an exotic placement, exit now instead of\n // applying a delta and changing the arrow\n if (/top-left|top-right|bottom-left|bottom-right/.test(placement)) return;\n\n var delta = getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);\n\n if (delta.left) {\n offset.left += delta.left;\n } else {\n offset.top += delta.top;\n }\n\n dimensions.setOffset(tip, offset);\n\n if (/top|right|bottom|left/.test(placement)) {\n var isVertical = /top|bottom/.test(placement),\n arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight,\n arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';\n\n replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical);\n }\n }\n\n function getViewportAdjustedDelta(placement, position, actualWidth, actualHeight) {\n var delta = { top: 0, left: 0 },\n $viewport = options.viewport && findElement(options.viewport.selector || options.viewport);\n\n if (!$viewport) {\n return delta;\n }\n\n var viewportPadding = options.viewport && options.viewport.padding || 0,\n viewportDimensions = getPosition($viewport);\n\n if (/right|left/.test(placement)) {\n var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll,\n bottomEdgeOffset = position.top + viewportPadding - viewportDimensions.scroll + actualHeight;\n if (topEdgeOffset < viewportDimensions.top) { // top overflow\n delta.top = viewportDimensions.top - topEdgeOffset;\n } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;\n }\n } else {\n var leftEdgeOffset = position.left - viewportPadding,\n rightEdgeOffset = position.left + viewportPadding + actualWidth;\n if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n delta.left = viewportDimensions.left - leftEdgeOffset;\n } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow\n delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;\n }\n }\n\n return delta;\n }\n\n function replaceArrow(delta, dimension, isHorizontal) {\n var $arrow = findElement('.tooltip-arrow, .arrow', tipElement[0]);\n\n $arrow.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')\n .css(isHorizontal ? 'top' : 'left', '');\n }\n\n function destroyTipElement() {\n // Cancel pending callbacks\n clearTimeout(timeout);\n\n if($tooltip.$isShown && tipElement !== null) {\n if(options.autoClose) {\n unbindAutoCloseEvents();\n }\n\n if(options.keyboard) {\n unbindKeyboardEvents();\n }\n }\n\n if(tipScope) {\n tipScope.$destroy();\n tipScope = null;\n }\n\n if(tipElement) {\n tipElement.remove();\n tipElement = $tooltip.$element = null;\n }\n }\n\n return $tooltip;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return TooltipFactory;\n\n };\n\n })\n\n .directive('bsTooltip', function($window, $location, $sce, $tooltip, $$rAF) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Observe scope attributes for change\n attr.$observe('title', function(newValue) {\n if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n var oldValue = scope.title;\n scope.title = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }\n });\n\n // Support scope as an object\n attr.bsTooltip && scope.$watch(attr.bsTooltip, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.title = newValue;\n }\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n newValue === true ? tooltip.show() : tooltip.hide();\n });\n\n // Enabled binding support\n attr.bsEnabled && scope.$watch(attr.bsEnabled, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n newValue === false ? tooltip.setEnabled(false) : tooltip.setEnabled(true);\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n tooltip.setViewport(newValue);\n });\n\n // Initialize popover\n var tooltip = $tooltip(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(tooltip) tooltip.destroy();\n options = null;\n tooltip = null;\n });\n\n }\n };\n\n });\n\n// Source: typeahead/typeahead.js\nangular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$typeahead', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'typeahead',\n prefixEvent: '$typeahead',\n placement: 'bottom-left',\n template: 'typeahead/typeahead.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n minLength: 1,\n filter: 'filter',\n limit: 6,\n autoSelect: false,\n comparator: '',\n trimValue: true\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n\n function TypeaheadFactory(element, controller, config) {\n\n var $typeahead = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $typeahead = $tooltip(element, options);\n var parentScope = config.scope;\n var scope = $typeahead.$scope;\n\n scope.$resetMatches = function(){\n scope.$matches = [];\n scope.$activeIndex = options.autoSelect ? 0 : -1; // If set to 0, the first match will be highlighted\n };\n scope.$resetMatches();\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $typeahead.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $typeahead.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $typeahead.$isVisible();\n };\n\n // Public methods\n\n $typeahead.update = function(matches) {\n scope.$matches = matches;\n if(scope.$activeIndex >= matches.length) {\n scope.$activeIndex = options.autoSelect ? 0: -1;\n }\n\n // When the placement is not one of the bottom placements, re-calc the positioning\n // so the results render correctly.\n if (/^(bottom|bottom-left|bottom-right)$/.test(options.placement)) return;\n\n // wrap in a $timeout so the results are updated\n // before repositioning\n $timeout($typeahead.$applyPlacement);\n };\n\n $typeahead.activate = function(index) {\n scope.$activeIndex = index;\n };\n\n $typeahead.select = function(index) {\n if(index === -1) return;\n var value = scope.$matches[index].value;\n // console.log('$setViewValue', value);\n controller.$setViewValue(value);\n controller.$render();\n scope.$resetMatches();\n if(parentScope) parentScope.$digest();\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $typeahead);\n };\n\n // Protected methods\n\n $typeahead.$isVisible = function() {\n if(!options.minLength || !controller) {\n return !!scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength;\n };\n\n $typeahead.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $typeahead.$onMouseDown = function(evt) {\n // Prevent blur on mousedown\n evt.preventDefault();\n evt.stopPropagation();\n };\n\n $typeahead.$onKeyDown = function(evt) {\n if(!/(38|40|13)/.test(evt.keyCode)) return;\n\n // Let ngSubmit pass if the typeahead tip is hidden or no option is selected\n if($typeahead.$isVisible() && !(evt.keyCode === 13 && scope.$activeIndex === -1)) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n // Select with enter\n if(evt.keyCode === 13 && scope.$matches.length) {\n $typeahead.select(scope.$activeIndex);\n }\n\n // Navigate with keyboard\n else if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n };\n\n // Overrides\n\n var show = $typeahead.show;\n $typeahead.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $typeahead.$onKeyDown);\n }\n }, 0, false);\n };\n\n var hide = $typeahead.hide;\n $typeahead.hide = function() {\n $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $typeahead.$onKeyDown);\n }\n if(!options.autoSelect)\n $typeahead.activate(-1);\n hide();\n };\n\n return $typeahead;\n\n }\n\n TypeaheadFactory.defaults = defaults;\n return TypeaheadFactory;\n\n };\n\n })\n\n .directive('bsTypeahead', function($window, $parse, $q, $typeahead, $parseOptions) {\n\n var defaults = $typeahead.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'filter', 'limit', 'minLength', 'watchOptions', 'selectMode', 'autoSelect', 'comparator', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'trimValue'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n });\n\n // Disable browser autocompletion\n element.attr('autocomplete' ,'off');\n\n // Build proper bsOptions\n var filter = options.filter || defaults.filter;\n var limit = options.limit || defaults.limit;\n var comparator = options.comparator || defaults.comparator;\n\n var bsOptions = attr.bsOptions;\n if(filter) bsOptions += ' | ' + filter + ':$viewValue';\n if (comparator) bsOptions += ':' + comparator;\n if(limit) bsOptions += ' | limitTo:' + limit;\n var parsedOptions = $parseOptions(bsOptions);\n\n // Initialize typeahead\n var typeahead = $typeahead(element, controller, options);\n\n // Watch options on demand\n if(options.watchOptions) {\n // Watch bsOptions values before filtering for changes, drop function calls\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n scope.$watchCollection(watchedOptions, function (newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller).then(function (values) {\n typeahead.update(values);\n controller.$render();\n });\n });\n }\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('$watch', element.attr('ng-model'), newValue);\n scope.$modelValue = newValue; // Publish modelValue on scope for custom templates\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n // Prevent input with no future prospect if selectMode is truthy\n // @TODO test selectMode\n if(options.selectMode && !values.length && newValue.length > 0) {\n controller.$setViewValue(controller.$viewValue.substring(0, controller.$viewValue.length - 1));\n return;\n }\n if(values.length > limit) values = values.slice(0, limit);\n var isVisible = typeahead.$isVisible();\n isVisible && typeahead.update(values);\n // Do not re-queue an update if a correct value has been selected\n if(values.length === 1 && values[0].value === newValue) return;\n !isVisible && typeahead.update(values);\n // Queue a new rendering that will leverage collection loading\n controller.$render();\n });\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var displayValue = parsedOptions.displayValue(modelValue);\n return displayValue === undefined ? '' : displayValue;\n });\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n if(controller.$isEmpty(controller.$viewValue)) return element.val('');\n var index = typeahead.$getIndex(controller.$modelValue);\n var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;\n selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;\n var value = selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '') : '';\n element.val(options.trimValue === false ? value : value.trim());\n };\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (typeahead) typeahead.destroy();\n options = null;\n typeahead = null;\n });\n\n }\n };\n\n });\n\n})(window, document);\n","'use strict';\n\nangular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mgcrea.ngStrap.helpers.debounce'])\n\n .provider('$affix', function() {\n\n var defaults = this.defaults = {\n offsetTop: 'auto',\n inlineStyles: true\n };\n\n this.$get = function($window, debounce, dimensions) {\n\n var bodyEl = angular.element($window.document.body);\n var windowEl = angular.element($window);\n\n function AffixFactory(element, config) {\n\n var $affix = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var targetEl = options.target;\n\n // Initial private vars\n var reset = 'affix affix-top affix-bottom',\n setWidth = false,\n initialAffixTop = 0,\n initialOffsetTop = 0,\n offsetTop = 0,\n offsetBottom = 0,\n affixed = null,\n unpin = null;\n\n var parent = element.parent();\n // Options: custom parent\n if (options.offsetParent) {\n if (options.offsetParent.match(/^\\d+$/)) {\n for (var i = 0; i < (options.offsetParent * 1) - 1; i++) {\n parent = parent.parent();\n }\n }\n else {\n parent = angular.element(options.offsetParent);\n }\n }\n\n $affix.init = function() {\n\n this.$parseOffsets();\n initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n setWidth = !element[0].style.width;\n\n // Bind events\n targetEl.on('scroll', this.checkPosition);\n targetEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', this.$debouncedOnResize);\n\n // Both of these checkPosition() calls are necessary for the case where\n // the user hits refresh after scrolling to the bottom of the page.\n this.checkPosition();\n this.checkPositionWithEventLoop();\n\n };\n\n $affix.destroy = function() {\n\n // Unbind events\n targetEl.off('scroll', this.checkPosition);\n targetEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', this.$debouncedOnResize);\n\n };\n\n $affix.checkPositionWithEventLoop = function() {\n\n // IE 9 throws an error if we use 'this' instead of '$affix'\n // in this setTimeout call\n setTimeout($affix.checkPosition, 1);\n\n };\n\n $affix.checkPosition = function() {\n // if (!this.$element.is(':visible')) return\n\n var scrollTop = getScrollTop();\n var position = dimensions.offset(element[0]);\n var elementHeight = dimensions.height(element[0]);\n\n // Get required affix class according to position\n var affix = getRequiredAffixClass(unpin, position, elementHeight);\n\n // Did affix status changed this last check?\n if(affixed === affix) return;\n affixed = affix;\n\n // Add proper affix class\n element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\n\n if(affix === 'top') {\n unpin = null;\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', '');\n }\n } else if(affix === 'bottom') {\n if (options.offsetUnpin) {\n unpin = -(options.offsetUnpin * 1);\n }\n else {\n // Calculate unpin threshold when affixed to bottom.\n // Hopefully the browser scrolls pixel by pixel.\n unpin = position.top - scrollTop;\n }\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n }\n } else { // affix === 'middle'\n unpin = null;\n if(setWidth) {\n element.css('width', element[0].offsetWidth + 'px');\n }\n if (options.inlineStyles) {\n element.css('position', 'fixed');\n element.css('top', initialAffixTop + 'px');\n }\n }\n\n };\n\n $affix.$onResize = function() {\n $affix.$parseOffsets();\n $affix.checkPosition();\n };\n $affix.$debouncedOnResize = debounce($affix.$onResize, 50);\n\n $affix.$parseOffsets = function() {\n var initialPosition = element.css('position');\n // Reset position to calculate correct offsetTop\n if (options.inlineStyles){\n element.css('position', (options.offsetParent) ? '' : 'relative');\n }\n\n if(options.offsetTop) {\n if(options.offsetTop === 'auto') {\n options.offsetTop = '+0';\n }\n if(options.offsetTop.match(/^[-+]\\d+$/)) {\n initialAffixTop = - options.offsetTop * 1;\n if(options.offsetParent) {\n offsetTop = dimensions.offset(parent[0]).top + (options.offsetTop * 1);\n }\n else {\n offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\n }\n }\n else {\n offsetTop = options.offsetTop * 1;\n }\n }\n\n if(options.offsetBottom) {\n if(options.offsetParent && options.offsetBottom.match(/^[-+]\\d+$/)) {\n // add 1 pixel due to rounding problems...\n offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + (options.offsetBottom * 1) + 1;\n }\n else {\n offsetBottom = options.offsetBottom * 1;\n }\n }\n\n // Bring back the element's position after calculations\n if (options.inlineStyles){\n element.css('position', initialPosition);\n }\n };\n\n // Private methods\n\n function getRequiredAffixClass(unpin, position, elementHeight) {\n\n var scrollTop = getScrollTop();\n var scrollHeight = getScrollHeight();\n\n if(scrollTop <= offsetTop) {\n return 'top';\n } else if(unpin !== null && (scrollTop + unpin <= position.top)) {\n return 'middle';\n } else if(offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n return 'bottom';\n } else {\n return 'middle';\n }\n\n }\n\n function getScrollTop() {\n return targetEl[0] === $window ? $window.pageYOffset : targetEl[0].scrollTop;\n }\n\n function getScrollHeight() {\n return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight;\n }\n\n $affix.init();\n return $affix;\n\n }\n\n return AffixFactory;\n\n };\n\n })\n\n .directive('bsAffix', function($affix, $window) {\n\n return {\n restrict: 'EAC',\n require: '^?bsAffixTarget',\n link: function postLink(scope, element, attr, affixTarget) {\n\n var options = {scope: scope, target: affixTarget ? affixTarget.$element : angular.element($window)};\n angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin', 'inlineStyles'], function(key) {\n if(angular.isDefined(attr[key])) {\n var option = attr[key];\n if (/true/i.test(option)) option = true;\n if (/false/i.test(option)) option = false;\n options[key] = option;\n }\n });\n\n var affix = $affix(element, options);\n scope.$on('$destroy', function() {\n affix && affix.destroy();\n options = null;\n affix = null;\n });\n\n }\n };\n\n })\n\n .directive('bsAffixTarget', function() {\n return {\n controller: function($element) {\n this.$element = $element;\n }\n };\n });\n","'use strict';\n\n// @BUG: following snippet won't compile correctly\n// @TODO: submit issue to core\n// ' ' +\n\nangular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal'])\n\n .provider('$alert', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'alert',\n prefixEvent: 'alert',\n placement: null,\n template: 'alert/alert.tpl.html',\n container: false,\n element: null,\n backdrop: false,\n keyboard: true,\n show: true,\n // Specific options\n duration: false,\n type: false,\n dismissable: true\n };\n\n this.$get = function($modal, $timeout) {\n\n function AlertFactory(config) {\n\n var $alert = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $alert = $modal(options);\n\n // Support scope as string options [/*title, content, */ type, dismissable]\n $alert.$scope.dismissable = !!options.dismissable;\n if(options.type) {\n $alert.$scope.type = options.type;\n }\n\n // Support auto-close duration\n var show = $alert.show;\n if(options.duration) {\n $alert.show = function() {\n show();\n $timeout(function() {\n $alert.hide();\n }, options.duration * 1000);\n };\n }\n\n return $alert;\n\n }\n\n return AlertFactory;\n\n };\n\n })\n\n .directive('bsAlert', function($window, $sce, $alert) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'placement', 'keyboard', 'html', 'container', 'animation', 'duration', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['keyboard', 'html', 'container', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content', 'type'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAlert && scope.$watch(attr.bsAlert, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize alert\n var alert = $alert(options);\n\n // Trigger\n element.on(attr.trigger || 'click', alert.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (alert) alert.destroy();\n options = null;\n alert = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal'])\n\n .provider('$aside', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade-and-slide-right',\n prefixClass: 'aside',\n prefixEvent: 'aside',\n placement: 'right',\n template: 'aside/aside.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($modal) {\n\n function AsideFactory(config) {\n\n var $aside = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $aside = $modal(options);\n\n return $aside;\n\n }\n\n return AsideFactory;\n\n };\n\n })\n\n .directive('bsAside', function($window, $sce, $aside) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAside && scope.$watch(attr.bsAside, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize aside\n var aside = $aside(options);\n\n // Trigger\n element.on(attr.trigger || 'click', aside.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (aside) aside.destroy();\n options = null;\n aside = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.button', [])\n\n .provider('$button', function() {\n\n var defaults = this.defaults = {\n activeClass:'active',\n toggleEvent:'click'\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsCheckboxGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"checkbox\"]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.attr('bs-checkbox', '');\n childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));\n });\n }\n\n };\n\n })\n\n .directive('bsCheckbox', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support label > input[type=\"checkbox\"]\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;\n if(constantValueRegExp.test(attr.trueValue)) {\n trueValue = scope.$eval(attr.trueValue);\n }\n var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;\n if(constantValueRegExp.test(attr.falseValue)) {\n falseValue = scope.$eval(attr.falseValue);\n }\n\n // Parse exotic values\n var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';\n if(hasExoticValues) {\n controller.$parsers.push(function(viewValue) {\n // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue);\n return viewValue ? trueValue : falseValue;\n });\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n return angular.equals(modelValue, trueValue);\n });\n // Fix rendering for exotic values\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n controller.$render();\n });\n }\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, trueValue);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n if(!isInput) {\n controller.$setViewValue(!activeElement.hasClass('active'));\n }\n if(!hasExoticValues) {\n controller.$render();\n }\n });\n });\n\n }\n\n };\n\n })\n\n .directive('bsRadioGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"radio\"]');\n angular.forEach(children, function(child) {\n angular.element(child).attr('bs-radio', '');\n angular.element(child).attr('ng-model', attr.ngModel);\n });\n }\n\n };\n\n })\n\n .directive('bsRadio', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support `label > input[type=\"radio\"]` markup\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var value;\n attr.$observe('value', function(v) {\n value = constantValueRegExp.test(v) ? scope.$eval(v) : v;\n controller.$render();\n });\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, value);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n controller.$setViewValue(value);\n controller.$render();\n });\n });\n\n }\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.collapse', [])\n\n .provider('$collapse', function() {\n\n var defaults = this.defaults = {\n animation: 'am-collapse',\n disallowToggle: false,\n activeClass: 'in',\n startCollapsed: false,\n allowMultiple: false\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['disallowToggle', 'startCollapsed', 'allowMultiple'], function(key) {\n if(angular.isDefined($attrs[key]) && falseValueRegExp.test($attrs[key]))\n self.$options[key] = false;\n });\n\n self.$toggles = [];\n self.$targets = [];\n\n self.$viewChangeListeners = [];\n\n self.$registerToggle = function(element) {\n self.$toggles.push(element);\n };\n self.$registerTarget = function(element) {\n self.$targets.push(element);\n };\n\n self.$unregisterToggle = function(element) {\n var index = self.$toggles.indexOf(element);\n // remove toggle from $toggles array\n self.$toggles.splice(index, 1);\n };\n self.$unregisterTarget = function(element) {\n var index = self.$targets.indexOf(element);\n\n // remove element from $targets array\n self.$targets.splice(index, 1);\n\n if (self.$options.allowMultiple) {\n // remove target index from $active array values\n deactivateItem(element);\n }\n\n // fix active item indexes\n fixActiveItemIndexes(index);\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n // use array to store all the currently open panels\n self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n self.$setActive = $scope.$setActive = function(value) {\n if(angular.isArray(value)) {\n self.$targets.$active = angular.copy(value);\n }\n else if(!self.$options.disallowToggle) {\n // toogle element active status\n isActive(value) ? deactivateItem(value) : activateItem(value);\n } else {\n activateItem(value);\n }\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$activeIndexes = function() {\n return self.$options.allowMultiple ? self.$targets.$active :\n self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n };\n\n function fixActiveItemIndexes(index) {\n // item with index was removed, so we\n // need to adjust other items index values\n var activeIndexes = self.$targets.$active;\n for(var i = 0; i < activeIndexes.length; i++) {\n if (index < activeIndexes[i]) {\n activeIndexes[i] = activeIndexes[i] - 1;\n }\n\n // the last item is active, so we need to\n // adjust its index\n if (activeIndexes[i] === self.$targets.length) {\n activeIndexes[i] = self.$targets.length - 1;\n }\n }\n }\n\n function isActive(value) {\n var activeItems = self.$targets.$active;\n return activeItems.indexOf(value) === -1 ? false : true;\n }\n\n function deactivateItem(value) {\n var index = self.$targets.$active.indexOf(value);\n if (index !== -1) {\n self.$targets.$active.splice(index, 1);\n }\n }\n\n function activateItem(value) {\n if (!self.$options.allowMultiple) {\n // remove current selected item\n self.$targets.$active.splice(0, 1);\n }\n\n if (self.$targets.$active.indexOf(value) === -1) {\n self.$targets.$active.push(value);\n }\n }\n\n };\n\n this.$get = function() {\n var $collapse = {};\n $collapse.defaults = defaults;\n $collapse.controller = controller;\n return $collapse;\n };\n\n })\n\n .directive('bsCollapse', function($window, $animate, $collapse) {\n\n var defaults = $collapse.defaults;\n\n return {\n require: ['?ngModel', 'bsCollapse'],\n controller: ['$scope', '$element', '$attrs', $collapse.controller],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n if (angular.isArray(modelValue)) {\n // model value is an array, so just replace\n // the active items directly\n bsCollapseCtrl.$setActive(modelValue);\n }\n else {\n var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n if (angular.isArray(activeIndexes)) {\n // we have an array of selected indexes\n if (activeIndexes.indexOf(modelValue * 1) === -1) {\n // item with modelValue index is not active\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n else if (activeIndexes !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n return modelValue;\n });\n\n }\n\n }\n };\n\n })\n\n .directive('bsCollapseToggle', function() {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base attr\n element.attr('data-toggle', 'collapse');\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerToggle(element);\n\n // remove toggle from collapse controller when toggle is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterToggle(element);\n });\n\n element.on('click', function() {\n var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n bsCollapseCtrl.$setActive(index * 1);\n scope.$apply();\n });\n\n }\n };\n\n })\n\n .directive('bsCollapseTarget', function($animate) {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n // scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base class\n element.addClass('collapse');\n\n // Add animation class\n if(bsCollapseCtrl.$options.animation) {\n element.addClass(bsCollapseCtrl.$options.animation);\n }\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerTarget(element);\n\n // remove pane target from collapse controller when target is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterTarget(element);\n });\n\n function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$activeIndexes();\n var action = 'removeClass';\n if (angular.isArray(active)) {\n if (active.indexOf(index) !== -1) {\n action = 'addClass';\n }\n }\n else if (index === active) {\n action = 'addClass';\n }\n\n $animate[action](element, bsCollapseCtrl.$options.activeClass);\n }\n\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.datepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$datepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'datepicker',\n prefixClass: 'datepicker',\n placement: 'bottom-left',\n template: 'datepicker/datepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: false,\n dateType: 'date',\n dateFormat: 'shortDate',\n timezone: null,\n modelDateFormat: null,\n dayFormat: 'dd',\n monthFormat: 'MMM',\n yearFormat: 'yyyy',\n monthTitleFormat: 'MMMM yyyy',\n yearTitleFormat: 'yyyy',\n strictFormat: false,\n autoclose: false,\n minDate: -Infinity,\n maxDate: +Infinity,\n startView: 0,\n minView: 0,\n startWeek: 0,\n daysOfWeekDisabled: '',\n iconLeft: 'glyphicon glyphicon-chevron-left',\n iconRight: 'glyphicon glyphicon-chevron-right'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function DatepickerFactory(element, controller, config) {\n\n var $datepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $datepicker.$options;\n var scope = $datepicker.$scope;\n if(options.startView) options.startView -= options.minView;\n\n // View vars\n\n var pickerViews = datepickerViews($datepicker);\n $datepicker.$views = pickerViews.views;\n var viewDate = pickerViews.viewDate;\n scope.$mode = options.startView;\n scope.$iconLeft = options.iconLeft;\n scope.$iconRight = options.iconRight;\n var $picker = $datepicker.$views[scope.$mode];\n\n // Scope methods\n\n scope.$select = function(date) {\n $datepicker.select(date);\n };\n scope.$selectPane = function(value) {\n $datepicker.$selectPane(value);\n };\n scope.$toggleMode = function() {\n $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);\n };\n\n // Public methods\n\n $datepicker.update = function(date) {\n // console.warn('$datepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $datepicker.$date = date;\n $picker.update.call($picker, date);\n }\n // Build only if pristine\n $datepicker.$build(true);\n };\n\n $datepicker.updateDisabledDates = function(dateRanges) {\n options.disabledDateRanges = dateRanges;\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);\n }\n };\n\n $datepicker.select = function(date, keep) {\n // console.warn('$datepicker.select', date, scope.$mode);\n if(!angular.isDate(controller.$dateValue)) controller.$dateValue = new Date(date);\n if(!scope.$mode || keep) {\n controller.$setViewValue(angular.copy(date));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $datepicker.hide(true); });\n }\n } else {\n angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});\n $datepicker.setMode(scope.$mode - 1);\n $datepicker.$build();\n }\n };\n\n $datepicker.setMode = function(mode) {\n // console.warn('$datepicker.setMode', mode);\n scope.$mode = mode;\n $picker = $datepicker.$views[scope.$mode];\n $datepicker.$build();\n };\n\n // Protected methods\n\n $datepicker.$build = function(pristine) {\n // console.warn('$datepicker.$build() viewDate=%o', viewDate);\n if(pristine === true && $picker.built) return;\n if(pristine === false && !$picker.built) return;\n $picker.build.call($picker);\n };\n\n $datepicker.$updateSelected = function() {\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], updateSelected);\n }\n };\n\n $datepicker.$isSelected = function(date) {\n return $picker.isSelected(date);\n };\n\n $datepicker.$setDisabledEl = function(el) {\n el.disabled = $picker.isDisabled(el.date);\n };\n\n $datepicker.$selectPane = function(value) {\n var steps = $picker.steps;\n // set targetDate to first day of month to avoid problems with\n // date values rollover. This assumes the viewDate does not\n // depend on the day of the month\n var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));\n angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});\n $datepicker.$build();\n };\n\n $datepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $datepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n if(evt.keyCode === 13) {\n if(!scope.$mode) {\n return $datepicker.hide(true);\n } else {\n return scope.$apply(function() { $datepicker.setMode(scope.$mode - 1); });\n }\n }\n\n // Navigate with keyboard\n $picker.onKeyDown(evt);\n parentScope.$digest();\n };\n\n // Private\n\n function updateSelected(el) {\n el.selected = $datepicker.$isSelected(el.date);\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $datepicker.init;\n $datepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'date');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $datepicker.destroy;\n $datepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $datepicker.show;\n $datepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // if $datepicker is no longer showing, don't setup events\n if(!$datepicker.$isShown) return;\n $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $datepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $datepicker.hide;\n $datepicker.hide = function(blur) {\n if(!$datepicker.$isShown) return;\n $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $datepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $datepicker;\n\n }\n\n DatepickerFactory.defaults = defaults;\n return DatepickerFactory;\n\n };\n\n })\n\n .directive('bsDatepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {\n\n var defaults = $datepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'timezone', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!datepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);\n newValue === true ? datepicker.show() : datepicker.hide();\n });\n\n // Initialize datepicker\n var datepicker = $datepicker(element, controller, options);\n options = datepicker.$options;\n // Set expected iOS format\n if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';\n\n var lang = options.lang;\n\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n // Observe attributes for changes\n angular.forEach(['minDate', 'maxDate'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n // console.warn('attr.$observe(%s)=%o', key, newValue);\n datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);\n // Build only if dirty\n !isNaN(datepicker.$options[key]) && datepicker.$build(false);\n validateAgainstMinMaxDate(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n datepicker.update(controller.$dateValue);\n }, true);\n\n // Normalize undefined/null/empty array,\n // so that we don't treat changing from undefined->null as a change.\n function normalizeDateRanges(ranges) {\n if (!ranges || !ranges.length) return null;\n return ranges;\n }\n\n if (angular.isDefined(attr.disabledDates)) {\n scope.$watch(attr.disabledDates, function(disabledRanges, previousValue) {\n disabledRanges = normalizeDateRanges(disabledRanges);\n previousValue = normalizeDateRanges(previousValue);\n\n if (disabledRanges) {\n datepicker.updateDisabledDates(disabledRanges);\n }\n });\n }\n\n function validateAgainstMinMaxDate(parsedDate) {\n if (!angular.isDate(parsedDate)) return;\n var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;\n var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(isValid) controller.$dateValue = parsedDate;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n controller.$setValidity('date', true);\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n return null;\n }\n var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedDate || isNaN(parsedDate.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxDate(parsedDate);\n }\n\n if(options.dateType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedDate, options.timezone, true);\n return formatDate(date, options.modelDateFormat || options.dateFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.dateType === 'number') {\n return date.getTime();\n } else if(options.dateType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.dateType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.dateType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelDateFormat);\n } else if(options.dateType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) {\n // var today = new Date();\n // date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n // }\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getDateFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getDateFormattedString());\n };\n\n function getDateFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(datepicker) datepicker.destroy();\n options = null;\n datepicker = null;\n });\n\n }\n };\n\n })\n\n .provider('datepickerViews', function() {\n\n var defaults = this.defaults = {\n dayFormat: 'dd',\n daySplit: 7\n };\n\n // Split array into smaller arrays\n function split(arr, size) {\n var arrays = [];\n while(arr.length > 0) {\n arrays.push(arr.splice(0, size));\n }\n return arrays;\n }\n\n // Modulus operator\n function mod(n, m) {\n return ((n % m) + m) % m;\n }\n\n this.$get = function($dateFormatter, $dateParser, $sce) {\n\n return function(picker) {\n\n var scope = picker.$scope;\n var options = picker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n var weekDaysLabelsHtml = $sce.trustAsHtml('' + weekDaysLabels.join('') + '');\n\n var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n\n var views = [{\n format: options.dayFormat,\n split: 7,\n steps: { month: 1 },\n update: function(date, force) {\n if(!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getDate() !== viewDate.date || date.getDate() === 1) {\n // chaging picker current month will cause viewDate.date to be set to first day of the month,\n // in $datepicker.$selectPane, so picker would not update selected day display if\n // user picks first day of the new month.\n // As a workaround, we are always forcing update when picked date is first day of month.\n viewDate.date = picker.$date.getDate();\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5), firstDateOffset = firstDate.getTimezoneOffset();\n var today = dateParser.timezoneOffsetAdjust(new Date(), options.timezone).toDateString();\n // Handle daylight time switch\n if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);\n var days = [], day;\n for(var i = 0; i < 42; i++) { // < 7 * 6\n day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));\n days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n }\n scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);\n scope.showLabels = true;\n scope.labels = weekDaysLabelsHtml;\n scope.rows = split(days, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();\n },\n isDisabled: function(date) {\n var time = date.getTime();\n\n // Disabled because of min/max date.\n if (time < options.minDate || time > options.maxDate) return true;\n\n // Disabled due to being a disabled day of the week\n if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;\n\n // Disabled because of disabled date range.\n if (options.disabledDateRanges) {\n for (var i = 0; i < options.disabledDateRanges.length; i++) {\n if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {\n return true;\n }\n }\n }\n\n return false;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualTime = picker.$date.getTime();\n var newDate;\n\n if(evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);\n else if(evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);\n else if(evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);\n else if(evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'month',\n format: options.monthFormat,\n split: 4,\n steps: { year: 1 },\n update: function(date, force) {\n if(!this.built || date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstMonth = new Date(viewDate.year, 0, 1);\n var months = [], month;\n for (var i = 0; i < 12; i++) {\n month = new Date(viewDate.year, i, 1);\n months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n }\n scope.title = formatDate(month, options.yearTitleFormat);\n scope.showLabels = false;\n scope.rows = split(months, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualMonth = picker.$date.getMonth();\n var newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setMonth(actualMonth - 1);\n else if(evt.keyCode === 38) newDate.setMonth(actualMonth - 4);\n else if(evt.keyCode === 39) newDate.setMonth(actualMonth + 1);\n else if(evt.keyCode === 40) newDate.setMonth(actualMonth + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'year',\n format: options.yearFormat,\n split: 4,\n steps: { year: 12 },\n update: function(date, force) {\n if(!this.built || force || parseInt(date.getFullYear()/20, 10) !== parseInt(viewDate.year/20, 10)) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstYear = viewDate.year - viewDate.year % (this.split * 3);\n var years = [], year;\n for (var i = 0; i < 12; i++) {\n year = new Date(firstYear + i, 0, 1);\n years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});\n }\n scope.title = years[0].label + '-' + years[years.length - 1].label;\n scope.showLabels = false;\n scope.rows = split(years, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear() + 1, 0, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualYear = picker.$date.getFullYear(),\n newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setYear(actualYear - 1);\n else if(evt.keyCode === 38) newDate.setYear(actualYear - 4);\n else if(evt.keyCode === 39) newDate.setYear(actualYear + 1);\n else if(evt.keyCode === 40) newDate.setYear(actualYear + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }];\n\n return {\n views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,\n viewDate: viewDate\n };\n\n };\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$dropdown', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'dropdown',\n prefixEvent: 'dropdown',\n placement: 'bottom-left',\n template: 'dropdown/dropdown.tpl.html',\n trigger: 'click',\n container: false,\n keyboard: true,\n html: false,\n delay: 0\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;\n\n function DropdownFactory(element, config) {\n\n var $dropdown = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n $dropdown = $tooltip(element, options);\n var parentEl = element.parent();\n\n // Protected methods\n\n $dropdown.$onKeyDown = function(evt) {\n if (!/(38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Retrieve focused index\n var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));\n if(!items.length) return;\n var index;\n angular.forEach(items, function(el, i) {\n if(matchesSelector && matchesSelector.call(el, ':focus')) index = i;\n });\n\n // Navigate with keyboard\n if(evt.keyCode === 38 && index > 0) index--;\n else if(evt.keyCode === 40 && index < items.length - 1) index++;\n else if(angular.isUndefined(index)) index = 0;\n items.eq(index)[0].focus();\n\n };\n\n // Overrides\n\n var show = $dropdown.show;\n $dropdown.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n bodyEl.on('click', onBodyClick);\n }, 0, false);\n parentEl.hasClass('dropdown') && parentEl.addClass('open');\n };\n\n var hide = $dropdown.hide;\n $dropdown.hide = function() {\n if(!$dropdown.$isShown) return;\n options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n bodyEl.off('click', onBodyClick);\n parentEl.hasClass('dropdown') && parentEl.removeClass('open');\n hide();\n };\n\n var destroy = $dropdown.destroy;\n $dropdown.destroy = function() {\n bodyEl.off('click', onBodyClick);\n destroy();\n };\n\n // Private functions\n\n function onBodyClick(evt) {\n if(evt.target === element[0]) return;\n return evt.target !== element[0] && $dropdown.hide();\n }\n\n return $dropdown;\n\n }\n\n return DropdownFactory;\n\n };\n\n })\n\n .directive('bsDropdown', function($window, $sce, $dropdown) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as an object\n attr.bsDropdown && scope.$watch(attr.bsDropdown, function(newValue, oldValue) {\n scope.content = newValue;\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!dropdown || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(dropdown),?/i);\n newValue === true ? dropdown.show() : dropdown.hide();\n });\n\n // Initialize dropdown\n var dropdown = $dropdown(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (dropdown) dropdown.destroy();\n options = null;\n dropdown = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dateFormatter', [])\n\n .service('$dateFormatter', function($locale, dateFilter) {\n\n // The unused `lang` arguments are on purpose. The default implementation does not\n // use them and it always uses the locale loaded into the `$locale` service.\n // Custom implementations might use it, thus allowing different directives to\n // have different languages.\n\n this.getDefaultLocale = function() {\n return $locale.id;\n };\n\n // Format is either a data format name, e.g. \"shortTime\" or \"fullDate\", or a date format\n // Return either the corresponding date format or the given date format.\n this.getDatetimeFormat = function(format, lang) {\n return $locale.DATETIME_FORMATS[format] || format;\n };\n\n this.weekdaysShort = function(lang) {\n return $locale.DATETIME_FORMATS.SHORTDAY;\n };\n\n function splitTimeFormat(format) {\n return /(h+)([:\\.])?(m+)([:\\.])?(s*)[ ]?(a?)/i.exec(format).slice(1);\n }\n\n // h:mm a => h\n this.hoursFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[0];\n };\n\n // h:mm a => mm\n this.minutesFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[2];\n };\n\n // h:mm:ss a => ss\n this.secondsFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => :\n this.timeSeparator = function(timeFormat) {\n return splitTimeFormat(timeFormat)[1];\n };\n\n // h:mm:ss a => true, h:mm a => false\n this.showSeconds = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => true, H.mm => false\n this.showAM = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[5];\n };\n\n this.formatDate = function(date, format, lang, timezone){\n return dateFilter(date, format, timezone);\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dateParser', [])\n\n.provider('$dateParser', function($localeProvider) {\n\n // define a custom ParseDate object to use instead of native Date\n // to avoid date values wrapping when setting date component values\n function ParseDate() {\n this.year = 1970;\n this.month = 0;\n this.day = 1;\n this.hours = 0;\n this.minutes = 0;\n this.seconds = 0;\n this.milliseconds = 0;\n }\n\n ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };\n ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };\n ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };\n ParseDate.prototype.setHours = function(value) { this.hours = value; };\n ParseDate.prototype.getHours = function() { return this.hours; };\n ParseDate.prototype.setDate = function(value) { this.day = value; };\n ParseDate.prototype.setMonth = function(value) { this.month = value; };\n ParseDate.prototype.setFullYear = function(value) { this.year = value; };\n ParseDate.prototype.fromDate = function(value) {\n this.year = value.getFullYear();\n this.month = value.getMonth();\n this.day = value.getDate();\n this.hours = value.getHours();\n this.minutes = value.getMinutes();\n this.seconds = value.getSeconds();\n this.milliseconds = value.getMilliseconds();\n return this;\n };\n\n ParseDate.prototype.toDate = function() {\n return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n };\n\n var proto = ParseDate.prototype;\n\n function noop() {\n }\n\n function isNumeric(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n function indexOfCaseInsensitive(array, value) {\n var len = array.length, str=value.toString().toLowerCase();\n for (var i=0; i 12 when midnight changeover, but then cannot generate\n * midnight datetime, so jump to 1AM, otherwise reset.\n * @param date (Date) the date to check\n * @return (Date) the corrected date\n *\n * __ copied from jquery ui datepicker __\n */\n $dateParser.daylightSavingAdjust = function(date) {\n if (!date) {\n return null;\n }\n date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n return date;\n };\n\n /* Correct the date for timezone offset.\n * @param date (Date) the date to adjust\n * @param timezone (string) the timezone to adjust for\n * @param undo (boolean) to add or subtract timezone offset\n * @return (Date) the corrected date\n */\n $dateParser.timezoneOffsetAdjust = function(date, timezone, undo) {\n if (!date) {\n return null;\n }\n // Right now, only 'UTC' is supported.\n if (timezone && timezone === 'UTC') {\n date = new Date(date.getTime());\n date.setMinutes(date.getMinutes() + (undo?-1:1)*date.getTimezoneOffset());\n }\n return date;\n };\n\n // Private functions\n\n function setMapForFormat(format) {\n var keys = Object.keys(setFnMap), i;\n var map = [], sortedMap = [];\n // Map to setFn\n var clonedFormat = format;\n for(i = 0; i < keys.length; i++) {\n if(format.split(keys[i]).length > 1) {\n var index = clonedFormat.search(keys[i]);\n format = format.split(keys[i]).join('');\n if(setFnMap[keys[i]]) {\n map[index] = setFnMap[keys[i]];\n }\n }\n }\n // Sort result map\n angular.forEach(map, function(v) {\n // conditional required since angular.forEach broke around v1.2.21\n // related pr: https://github.com/angular/angular.js/pull/8525\n if(v) sortedMap.push(v);\n });\n return sortedMap;\n }\n\n function escapeReservedSymbols(text) {\n return text.replace(/\\//g, '[\\\\/]').replace('/-/g', '[-]').replace(/\\./g, '[.]').replace(/\\\\s/g, '[\\\\s]');\n }\n\n function regExpForFormat(format) {\n var keys = Object.keys(regExpMap), i;\n\n var re = format;\n // Abstract replaces to avoid collisions\n for(i = 0; i < keys.length; i++) {\n re = re.split(keys[i]).join('${' + i + '}');\n }\n // Replace abstracted values\n for(i = 0; i < keys.length; i++) {\n re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');\n }\n format = escapeReservedSymbols(format);\n\n return new RegExp('^' + re + '$', ['i']);\n }\n\n $dateParser.init();\n return $dateParser;\n\n };\n\n return DateParserFactory;\n\n };\n\n});\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.debounce', [])\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L693\n.factory('debounce', function($timeout) {\n return function(func, wait, immediate) {\n var timeout = null;\n return function() {\n var context = this,\n args = arguments,\n callNow = immediate && !timeout;\n if(timeout) {\n $timeout.cancel(timeout);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(!immediate) {\n func.apply(context, args);\n }\n }, wait, false);\n if(callNow) {\n func.apply(context, args);\n }\n return timeout;\n };\n };\n})\n\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L661\n.factory('throttle', function($timeout) {\n return function(func, wait, options) {\n var timeout = null;\n options || (options = {});\n return function() {\n var context = this,\n args = arguments;\n if(!timeout) {\n if(options.leading !== false) {\n func.apply(context, args);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(options.trailing !== false) {\n func.apply(context, args);\n }\n }, wait, false);\n }\n };\n };\n});\n\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n .factory('dimensions', function($document, $window) {\n\n var jqLite = angular.element;\n var fn = {};\n\n /**\n * Test the element nodeName\n * @param element\n * @param name\n */\n var nodeName = fn.nodeName = function(element, name) {\n return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();\n };\n\n /**\n * Returns the element computed style\n * @param element\n * @param prop\n * @param extra\n */\n fn.css = function(element, prop, extra) {\n var value;\n if (element.currentStyle) { //IE\n value = element.currentStyle[prop];\n } else if (window.getComputedStyle) {\n value = window.getComputedStyle(element)[prop];\n } else {\n value = element.style[prop];\n }\n return extra === true ? parseFloat(value) || 0 : value;\n };\n\n /**\n * Provides read-only equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.offset = function(element) {\n var boxRect = element.getBoundingClientRect();\n var docElement = element.ownerDocument;\n return {\n width: boxRect.width || element.offsetWidth,\n height: boxRect.height || element.offsetHeight,\n top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),\n left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)\n };\n };\n \n /**\n * Provides set equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip\n * @url http://api.jquery.com/offset/\n * @param element\n * @param options\n * @param i\n */\n fn.setOffset = function (element, options, i) {\n var curPosition,\n curLeft,\n curCSSTop,\n curTop,\n curOffset,\n curCSSLeft,\n calculatePosition,\n position = fn.css(element, 'position'),\n curElem = angular.element(element),\n props = {};\n \n // Set position first, in-case top/left are set even on static elem\n if (position === 'static') {\n element.style.position = 'relative';\n }\n \n curOffset = fn.offset(element);\n curCSSTop = fn.css(element, 'top');\n curCSSLeft = fn.css(element, 'left');\n calculatePosition = (position === 'absolute' || position === 'fixed') && \n (curCSSTop + curCSSLeft).indexOf('auto') > -1;\n \n // Need to be able to calculate position if either\n // top or left is auto and position is either absolute or fixed\n if (calculatePosition) {\n curPosition = fn.position(element);\n curTop = curPosition.top;\n curLeft = curPosition.left;\n } else {\n curTop = parseFloat(curCSSTop) || 0;\n curLeft = parseFloat(curCSSLeft) || 0;\n }\n \n if (angular.isFunction(options)) {\n options = options.call(element, i, curOffset);\n }\n \n if (options.top !== null ) {\n props.top = (options.top - curOffset.top) + curTop;\n }\n if ( options.left !== null ) {\n props.left = (options.left - curOffset.left) + curLeft;\n }\n\n if ('using' in options) {\n options.using.call(curElem, props);\n } else {\n curElem.css({\n top: props.top + 'px',\n left: props.left + 'px'\n });\n }\n };\n\n /**\n * Provides read-only equivalent of jQuery's position function\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.position = function(element) {\n\n var offsetParentRect = {top: 0, left: 0},\n offsetParentElement,\n offset;\n\n // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n if (fn.css(element, 'position') === 'fixed') {\n\n // We assume that getBoundingClientRect is available when computed position is fixed\n offset = element.getBoundingClientRect();\n\n } else {\n\n // Get *real* offsetParentElement\n offsetParentElement = offsetParent(element);\n\n // Get correct offsets\n offset = fn.offset(element);\n if (!nodeName(offsetParentElement, 'html')) {\n offsetParentRect = fn.offset(offsetParentElement);\n }\n\n // Add offsetParent borders\n offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);\n offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);\n }\n\n // Subtract parent offsets and element margins\n return {\n width: element.offsetWidth,\n height: element.offsetHeight,\n top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),\n left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)\n };\n\n };\n\n /**\n * Returns the closest, non-statically positioned offsetParent of a given element\n * @required-by fn.position\n * @param element\n */\n var offsetParent = function offsetParentElement(element) {\n var docElement = element.ownerDocument;\n var offsetParent = element.offsetParent || docElement;\n if(nodeName(offsetParent, '#document')) return docElement.documentElement;\n while(offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {\n offsetParent = offsetParent.offsetParent;\n }\n return offsetParent || docElement.documentElement;\n };\n\n /**\n * Provides equivalent of jQuery's height function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/height/\n * @param element\n * @param outer\n */\n fn.height = function(element, outer) {\n var value = element.offsetHeight;\n if(outer) {\n value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);\n } else {\n value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);\n }\n return value;\n };\n\n /**\n * Provides equivalent of jQuery's width function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/width/\n * @param element\n * @param outer\n */\n fn.width = function(element, outer) {\n var value = element.offsetWidth;\n if(outer) {\n value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);\n } else {\n value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);\n }\n return value;\n };\n\n return fn;\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.parseOptions', [])\n\n .provider('$parseOptions', function() {\n\n var defaults = this.defaults = {\n regexp: /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w]*)|(?:\\(\\s*([\\$\\w][\\$\\w]*)\\s*,\\s*([\\$\\w][\\$\\w]*)\\s*\\)))\\s+in\\s+(.*?)(?:\\s+track\\s+by\\s+(.*?))?$/\n };\n\n this.$get = function($parse, $q) {\n\n function ParseOptionsFactory(attr, config) {\n\n var $parseOptions = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n $parseOptions.$values = [];\n\n // Private vars\n var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;\n\n $parseOptions.init = function() {\n $parseOptions.$match = match = attr.match(options.regexp);\n displayFn = $parse(match[2] || match[1]),\n valueName = match[4] || match[6],\n keyName = match[5],\n groupByFn = $parse(match[3] || ''),\n valueFn = $parse(match[2] ? match[1] : valueName),\n valuesFn = $parse(match[7]);\n };\n\n $parseOptions.valuesFn = function(scope, controller) {\n return $q.when(valuesFn(scope, controller))\n .then(function(values) {\n $parseOptions.$values = values ? parseValues(values, scope) : {};\n return $parseOptions.$values;\n });\n };\n\n $parseOptions.displayValue = function(modelValue) {\n var scope = {};\n scope[valueName] = modelValue;\n return displayFn(scope);\n };\n\n // Private functions\n\n function parseValues(values, scope) {\n return values.map(function(match, index) {\n var locals = {}, label, value;\n locals[valueName] = match;\n label = displayFn(scope, locals);\n value = valueFn(scope, locals);\n return {label: label, value: value, index: index};\n });\n }\n\n $parseOptions.init();\n return $parseOptions;\n\n }\n\n return ParseOptionsFactory;\n\n };\n\n });\n","'use strict';\n\n(angular.version.minor < 3 && angular.version.dot < 14) && angular.module('ng')\n\n.factory('$$rAF', function($window, $timeout) {\n\n var requestAnimationFrame = $window.requestAnimationFrame ||\n $window.webkitRequestAnimationFrame ||\n $window.mozRequestAnimationFrame;\n\n var cancelAnimationFrame = $window.cancelAnimationFrame ||\n $window.webkitCancelAnimationFrame ||\n $window.mozCancelAnimationFrame ||\n $window.webkitCancelRequestAnimationFrame;\n\n var rafSupported = !!requestAnimationFrame;\n var raf = rafSupported ?\n function(fn) {\n var id = requestAnimationFrame(fn);\n return function() {\n cancelAnimationFrame(id);\n };\n } :\n function(fn) {\n var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n return function() {\n $timeout.cancel(timer);\n };\n };\n\n raf.supported = rafSupported;\n\n return raf;\n\n});\n\n// .factory('$$animateReflow', function($$rAF, $document) {\n\n// var bodyEl = $document[0].body;\n\n// return function(fn) {\n// //the returned function acts as the cancellation function\n// return $$rAF(function() {\n// //the line below will force the browser to perform a repaint\n// //so that all the animated elements within the animation frame\n// //will be properly updated and drawn on screen. This is\n// //required to perform multi-class CSS based animations with\n// //Firefox. DO NOT REMOVE THIS LINE.\n// var a = bodyEl.offsetWidth + 1;\n// fn();\n// });\n// };\n\n// });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$modal', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n backdropAnimation: 'am-fade',\n prefixClass: 'modal',\n prefixEvent: 'modal',\n placement: 'top',\n template: 'modal/modal.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {\n\n var forEach = angular.forEach;\n var trim = String.prototype.trim;\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n var bodyElement = angular.element($window.document.body);\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n\n function ModalFactory(config) {\n\n var $modal = {};\n\n // Common vars\n var options = $modal.$options = angular.extend({}, defaults, config);\n $modal.$promise = fetchTemplate(options.template);\n var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(!options.element && !options.container) {\n options.container = 'body';\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $modal.$id = options.id || options.element && options.element.attr('id') || '';\n\n // Support scope as string options\n forEach(['title', 'content'], function(key) {\n if(options[key]) scope[key] = $sce.trustAsHtml(options[key]);\n });\n\n // Provide scope helpers\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $modal.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $modal.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $modal.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $modal.$isShown = scope.$isShown = false;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $modal.$promise = $modal.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);\n // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n if(!config.template) contentEl.next().remove();\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize modal\n var modalLinker, modalElement;\n var backdropElement = angular.element('
');\n backdropElement.css({position:'fixed', top:'0px', left:'0px', bottom:'0px', right:'0px', 'z-index': 1038});\n $modal.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n modalLinker = $compile(template);\n $modal.init();\n });\n\n $modal.init = function() {\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n $modal.show();\n });\n }\n\n };\n\n $modal.destroy = function() {\n\n // Remove element\n if(modalElement) {\n modalElement.remove();\n modalElement = null;\n }\n if(backdropElement) {\n backdropElement.remove();\n backdropElement = null;\n }\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $modal.show = function() {\n if($modal.$isShown) return;\n\n var parent, after;\n if(angular.isElement(options.container)) {\n parent = options.container;\n after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;\n } else {\n if (options.container) {\n parent = findElement(options.container);\n after = parent[0] && parent[0].lastChild ? angular.element(parent[0].lastChild) : null;\n } else {\n parent = null;\n after = options.element;\n }\n }\n\n // Fetch a cloned element linked from template\n modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\n\n if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n return;\n }\n\n // Set the initial positioning.\n modalElement.css({display: 'block'}).addClass(options.placement);\n\n // Options: animation\n if(options.animation) {\n if(options.backdrop) {\n backdropElement.addClass(options.backdropAnimation);\n }\n modalElement.addClass(options.animation);\n }\n\n if(options.backdrop) {\n $animate.enter(backdropElement, bodyElement, null);\n }\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.enter(modalElement, parent, after, enterAnimateCallback);\n if(promise && promise.then) promise.then(enterAnimateCallback);\n\n $modal.$isShown = scope.$isShown = true;\n safeDigest(scope);\n // Focus once the enter-animation has started\n // Weird PhantomJS bug hack\n var el = modalElement[0];\n requestAnimationFrame(function() {\n el.focus();\n });\n\n bodyElement.addClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n }\n\n // Bind events\n if(options.backdrop) {\n modalElement.on('click', hideOnBackdropClick);\n backdropElement.on('click', hideOnBackdropClick);\n backdropElement.on('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.on('keyup', $modal.$onKeyUp);\n }\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $modal);\n }\n\n $modal.hide = function() {\n if(!$modal.$isShown) return;\n\n if(scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {\n return;\n }\n var promise = $animate.leave(modalElement, leaveAnimateCallback);\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n if(options.backdrop) {\n $animate.leave(backdropElement);\n }\n $modal.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.backdrop) {\n modalElement.off('click', hideOnBackdropClick);\n backdropElement.off('click', hideOnBackdropClick);\n backdropElement.off('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.off('keyup', $modal.$onKeyUp);\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $modal);\n bodyElement.removeClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n }\n }\n\n $modal.toggle = function() {\n\n $modal.$isShown ? $modal.hide() : $modal.show();\n\n };\n\n $modal.focus = function() {\n modalElement[0].focus();\n };\n\n // Protected methods\n\n $modal.$onKeyUp = function(evt) {\n\n if (evt.which === 27 && $modal.$isShown) {\n $modal.hide();\n evt.stopPropagation();\n }\n\n };\n\n // Private methods\n\n function hideOnBackdropClick(evt) {\n if(evt.target !== evt.currentTarget) return;\n options.backdrop === 'static' ? $modal.focus() : $modal.hide();\n }\n\n function preventEventDefault(evt) {\n evt.preventDefault();\n }\n\n return $modal;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return ModalFactory;\n\n };\n\n })\n\n .directive('bsModal', function($window, $sce, $modal) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsModal && scope.$watch(attr.bsModal, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize modal\n var modal = $modal(options);\n\n // Trigger\n element.on(attr.trigger || 'click', modal.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (modal) modal.destroy();\n options = null;\n modal = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.navbar', [])\n\n .provider('$navbar', function() {\n\n var defaults = this.defaults = {\n activeClass: 'active',\n routeAttr: 'data-match-route',\n strict: false\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsNavbar', function($window, $location, $navbar) {\n\n var defaults = $navbar.defaults;\n\n return {\n restrict: 'A',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = angular.copy(defaults);\n angular.forEach(Object.keys(defaults), function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Watch for the $location\n scope.$watch(function() {\n\n return $location.path();\n\n }, function(newValue, oldValue) {\n\n var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');\n\n angular.forEach(liElements, function(li) {\n\n var liElement = angular.element(li);\n var pattern = liElement.attr(options.routeAttr).replace('/', '\\\\/');\n if(options.strict) {\n pattern = '^' + pattern + '$';\n }\n var regexp = new RegExp(pattern, 'i');\n\n if(regexp.test(newValue)) {\n liElement.addClass(options.activeClass);\n } else {\n liElement.removeClass(options.activeClass);\n }\n\n });\n\n });\n\n }\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$popover', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n // uncommenting the next two lines will break backwards compatability\n // prefixClass: 'popover',\n // prefixEvent: 'popover',\n container: false,\n target: false,\n placement: 'right',\n template: 'popover/popover.tpl.html',\n contentTemplate: false,\n trigger: 'click',\n keyboard: true,\n html: false,\n title: '',\n content: '',\n delay: 0,\n autoClose: false\n };\n\n this.$get = function($tooltip) {\n\n function PopoverFactory(element, config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n var $popover = $tooltip(element, options);\n\n // Support scope as string options [/*title, */content]\n if(options.content) {\n $popover.$scope.content = options.content;\n }\n\n return $popover;\n\n }\n\n return PopoverFactory;\n\n };\n\n })\n\n .directive('bsPopover', function($window, $sce, $popover) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'customClass', 'autoClose', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoClose'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n });\n });\n\n // Support scope as an object\n attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);\n newValue === true ? popover.show() : popover.hide();\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n popover.setViewport(newValue);\n });\n\n // Initialize popover\n var popover = $popover(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (popover) popover.destroy();\n options = null;\n popover = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', 'mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$scrollspy', function() {\n\n // Pool of registered spies\n var spies = this.$$spies = {};\n\n var defaults = this.defaults = {\n debounce: 150,\n throttle: 100,\n offset: 100\n };\n\n this.$get = function($window, $document, $rootScope, dimensions, debounce, throttle) {\n\n var windowEl = angular.element($window);\n var docEl = angular.element($document.prop('documentElement'));\n var bodyEl = angular.element($window.document.body);\n\n // Helper functions\n\n function nodeName(element, name) {\n return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();\n }\n\n function ScrollSpyFactory(config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n if(!options.element) options.element = bodyEl;\n var isWindowSpy = nodeName(options.element, 'body');\n var scrollEl = isWindowSpy ? windowEl : options.element;\n var scrollId = isWindowSpy ? 'window' : options.id;\n\n // Use existing spy\n if(spies[scrollId]) {\n spies[scrollId].$$count++;\n return spies[scrollId];\n }\n\n var $scrollspy = {};\n\n // Private vars\n var unbindViewContentLoaded, unbindIncludeContentLoaded;\n var trackedElements = $scrollspy.$trackedElements = [];\n var sortedElements = [];\n var activeTarget;\n var debouncedCheckPosition;\n var throttledCheckPosition;\n var debouncedCheckOffsets;\n var viewportHeight;\n var scrollTop;\n\n $scrollspy.init = function() {\n\n // Setup internal ref counter\n this.$$count = 1;\n\n // Bind events\n debouncedCheckPosition = debounce(this.checkPosition, options.debounce);\n throttledCheckPosition = throttle(this.checkPosition, options.throttle);\n scrollEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', debouncedCheckPosition);\n scrollEl.on('scroll', throttledCheckPosition);\n\n debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);\n unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);\n unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);\n debouncedCheckOffsets();\n\n // Register spy for reuse\n if(scrollId) {\n spies[scrollId] = $scrollspy;\n }\n\n };\n\n $scrollspy.destroy = function() {\n\n // Check internal ref counter\n this.$$count--;\n if(this.$$count > 0) {\n return;\n }\n\n // Unbind events\n scrollEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', debouncedCheckPosition);\n scrollEl.off('scroll', throttledCheckPosition);\n unbindViewContentLoaded();\n unbindIncludeContentLoaded();\n if (scrollId) {\n delete spies[scrollId];\n }\n };\n\n $scrollspy.checkPosition = function() {\n\n // Not ready yet\n if(!sortedElements.length) return;\n\n // Calculate the scroll position\n scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;\n\n // Calculate the viewport height for use by the components\n viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));\n\n // Activate first element if scroll is smaller\n if(scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {\n return $scrollspy.$activateElement(sortedElements[0]);\n }\n\n // Activate proper element\n for (var i = sortedElements.length; i--;) {\n if(angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) continue;\n if(activeTarget === sortedElements[i].target) continue;\n if(scrollTop < sortedElements[i].offsetTop) continue;\n if(sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) continue;\n return $scrollspy.$activateElement(sortedElements[i]);\n }\n\n };\n\n $scrollspy.checkPositionWithEventLoop = function() {\n // IE 9 throws an error if we use 'this' instead of '$scrollspy'\n // in this setTimeout call\n setTimeout($scrollspy.checkPosition, 1);\n };\n\n // Protected methods\n\n $scrollspy.$activateElement = function(element) {\n if(activeTarget) {\n var activeElement = $scrollspy.$getTrackedElement(activeTarget);\n if(activeElement) {\n activeElement.source.removeClass('active');\n if(nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {\n activeElement.source.parent().parent().removeClass('active');\n }\n }\n }\n activeTarget = element.target;\n element.source.addClass('active');\n if(nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {\n element.source.parent().parent().addClass('active');\n }\n };\n\n $scrollspy.$getTrackedElement = function(target) {\n return trackedElements.filter(function(obj) {\n return obj.target === target;\n })[0];\n };\n\n // Track offsets behavior\n\n $scrollspy.checkOffsets = function() {\n\n angular.forEach(trackedElements, function(trackedElement) {\n var targetElement = document.querySelector(trackedElement.target);\n trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;\n if(options.offset && trackedElement.offsetTop !== null) trackedElement.offsetTop -= options.offset * 1;\n });\n\n sortedElements = trackedElements\n .filter(function(el) {\n return el.offsetTop !== null;\n })\n .sort(function(a, b) {\n return a.offsetTop - b.offsetTop;\n });\n\n debouncedCheckPosition();\n\n };\n\n $scrollspy.trackElement = function(target, source) {\n trackedElements.push({target: target, source: source});\n };\n\n $scrollspy.untrackElement = function(target, source) {\n var toDelete;\n for (var i = trackedElements.length; i--;) {\n if(trackedElements[i].target === target && trackedElements[i].source === source) {\n toDelete = i;\n break;\n }\n }\n trackedElements = trackedElements.splice(toDelete, 1);\n };\n\n $scrollspy.activate = function(i) {\n trackedElements[i].addClass('active');\n };\n\n // Initialize plugin\n\n $scrollspy.init();\n return $scrollspy;\n\n }\n\n return ScrollSpyFactory;\n\n };\n\n })\n\n .directive('bsScrollspy', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'EAC',\n link: function postLink(scope, element, attr) {\n\n var options = {scope: scope};\n angular.forEach(['offset', 'target'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n var scrollspy = $scrollspy(options);\n scrollspy.trackElement(options.target, element);\n\n scope.$on('$destroy', function() {\n if (scrollspy) {\n scrollspy.untrackElement(options.target, element);\n scrollspy.destroy();\n }\n options = null;\n scrollspy = null;\n });\n\n }\n };\n\n })\n\n\n .directive('bsScrollspyList', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'A',\n compile: function postLink(element, attr) {\n var children = element[0].querySelectorAll('li > a[href]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));\n });\n }\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$select', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'select',\n prefixEvent: '$select',\n placement: 'bottom-left',\n template: 'select/select.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n multiple: false,\n allNoneButtons: false,\n sort: true,\n caretHtml: ' ',\n placeholder: 'Choose among the following...',\n allText: 'All',\n noneText: 'None',\n maxLength: 3,\n maxLengthHtml: 'selected',\n iconCheckmark: 'glyphicon glyphicon-ok'\n };\n\n this.$get = function($window, $document, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n\n function SelectFactory(element, controller, config) {\n\n var $select = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $select = $tooltip(element, options);\n var scope = $select.$scope;\n\n scope.$matches = [];\n if (options.multiple) {\n scope.$activeIndex = [];\n }\n else {\n scope.$activeIndex = -1;\n }\n scope.$isMultiple = options.multiple;\n scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n scope.$iconCheckmark = options.iconCheckmark;\n scope.$allText = options.allText;\n scope.$noneText = options.noneText;\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $select.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $select.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $select.$isVisible();\n };\n\n scope.$isActive = function(index) {\n return $select.$isActive(index);\n };\n\n scope.$selectAll = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (!scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n scope.$selectNone = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n // Public methods\n\n $select.update = function(matches) {\n scope.$matches = matches;\n $select.$updateActiveIndex();\n };\n\n $select.activate = function(index) {\n if(options.multiple) {\n $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);\n if(options.sort) scope.$activeIndex.sort();\n } else {\n scope.$activeIndex = index;\n }\n return scope.$activeIndex;\n };\n\n $select.select = function(index) {\n var value = scope.$matches[index].value;\n scope.$apply(function() {\n $select.activate(index);\n if(options.multiple) {\n controller.$setViewValue(scope.$activeIndex.map(function(index) {\n return scope.$matches[index].value;\n }));\n } else {\n controller.$setViewValue(value);\n // Hide if single select\n $select.hide();\n }\n });\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $select);\n };\n\n // Protected methods\n\n $select.$updateActiveIndex = function() {\n if(controller.$modelValue && scope.$matches.length) {\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n scope.$activeIndex = controller.$modelValue.map(function(value) {\n return $select.$getIndex(value);\n });\n } else {\n scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n }\n } else if(scope.$activeIndex >= scope.$matches.length) {\n scope.$activeIndex = options.multiple ? [] : 0;\n }\n };\n\n $select.$isVisible = function() {\n if(!options.minLength || !controller) {\n return scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && controller.$viewValue.length >= options.minLength;\n };\n\n $select.$isActive = function(index) {\n if(options.multiple) {\n return scope.$activeIndex.indexOf(index) !== -1;\n } else {\n return scope.$activeIndex === index;\n }\n };\n\n $select.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $select.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n targetEl.triggerHandler('click');\n }\n };\n\n $select.$onKeyDown = function(evt) {\n if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // release focus on tab\n if (options.multiple && evt.keyCode === 9) {\n return $select.hide();\n }\n\n // Select with enter\n if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n return $select.select(scope.$activeIndex);\n }\n\n if (!options.multiple) {\n // Navigate with keyboard\n if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 38 && scope.$activeIndex < 0) scope.$activeIndex = scope.$matches.length - 1;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n }\n };\n\n // Overrides\n\n var _show = $select.show;\n $select.show = function() {\n _show();\n if(options.multiple) {\n $select.$element.addClass('select-multiple');\n }\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $select.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $select.hide;\n $select.hide = function() {\n if(!options.multiple && !controller.$modelValue) {\n scope.$activeIndex = -1;\n }\n $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $select.$onKeyDown);\n }\n _hide(true);\n };\n\n return $select;\n\n }\n\n SelectFactory.defaults = defaults;\n return SelectFactory;\n\n };\n\n })\n\n .directive('bsSelect', function($window, $parse, $q, $select, $parseOptions) {\n\n var defaults = $select.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, placeholder: defaults.placeholder};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'placeholder', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id', 'sort', 'caretHtml', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'allNoneButtons', 'sort'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Only parse data-multiple. Angular sets existence attributes to true (multiple/required/etc), they apply this\n // to data-multiple as well for some reason, so we'll parse this ourselves and disregard multiple\n var dataMultiple = element.attr('data-multiple');\n if(angular.isDefined(dataMultiple)) {\n if(falseValueRegExp.test(dataMultiple))\n options.multiple = false;\n else\n options.multiple = dataMultiple;\n }\n\n // Add support for select markup\n if(element[0].nodeName.toLowerCase() === 'select') {\n var inputEl = element;\n inputEl.css('display', 'none');\n element = angular.element('');\n inputEl.after(element);\n }\n\n // Build proper bsOptions\n var parsedOptions = $parseOptions(attr.bsOptions);\n\n // Initialize select\n var select = $select(element, controller, options);\n\n // Watch bsOptions values before filtering for changes\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n scope.$watchCollection(watchedOptions, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n select.update(values);\n controller.$render();\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n select.$updateActiveIndex();\n controller.$render();\n }, true);\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var selected, index;\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n selected = controller.$modelValue.map(function(value) {\n index = select.$getIndex(value);\n return angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }).filter(angular.isDefined);\n if(selected.length > (options.maxLength || defaults.maxLength)) {\n selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml);\n } else {\n selected = selected.join(', ');\n }\n } else {\n index = select.$getIndex(controller.$modelValue);\n selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }\n element.html((selected ? selected : options.placeholder) + (options.caretHtml ? options.caretHtml : defaults.caretHtml));\n };\n\n if(options.multiple){\n controller.$isEmpty = function(value){\n return !value || value.length === 0;\n };\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (select) select.destroy();\n options = null;\n select = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.timepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$timepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'timepicker',\n prefixClass: 'timepicker',\n placement: 'bottom-left',\n template: 'timepicker/timepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: true,\n timeType: 'date',\n timeFormat: 'shortTime',\n timezone: null,\n modelTimeFormat: null,\n autoclose: false,\n minTime: -Infinity,\n maxTime: +Infinity,\n length: 5,\n hourStep: 1,\n minuteStep: 5,\n secondStep: 5,\n roundDisplay: false,\n iconUp: 'glyphicon glyphicon-chevron-up',\n iconDown: 'glyphicon glyphicon-chevron-down',\n arrowBehavior: 'pager'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function timepickerFactory(element, controller, config) {\n\n var $timepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $timepicker.$options;\n var scope = $timepicker.$scope;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n function floorMinutes(time)\n {\n // coeff used to floor current time to nearest minuteStep interval\n var coeff = 1000 * 60 * options.minuteStep;\n return new Date(Math.floor(time.getTime() / coeff) * coeff);\n }\n\n // View vars\n\n var selectedIndex = 0;\n var defaultDate = options.roundDisplay ? floorMinutes(new Date()) : new Date();\n var startDate = controller.$dateValue || defaultDate;\n var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n var hoursFormat = $dateFormatter.hoursFormat(format),\n timeSeparator = $dateFormatter.timeSeparator(format),\n minutesFormat = $dateFormatter.minutesFormat(format),\n secondsFormat = $dateFormatter.secondsFormat(format),\n showSeconds = $dateFormatter.showSeconds(format),\n showAM = $dateFormatter.showAM(format);\n\n scope.$iconUp = options.iconUp;\n scope.$iconDown = options.iconDown;\n\n // Scope methods\n\n scope.$select = function(date, index) {\n $timepicker.select(date, index);\n };\n scope.$moveIndex = function(value, index) {\n $timepicker.$moveIndex(value, index);\n };\n scope.$switchMeridian = function(date) {\n $timepicker.switchMeridian(date);\n };\n\n // Public methods\n\n $timepicker.update = function(date) {\n // console.warn('$timepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $timepicker.$date = date;\n angular.extend(viewDate, {hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds(), millisecond: date.getMilliseconds()});\n $timepicker.$build();\n } else if(!$timepicker.$isBuilt) {\n $timepicker.$build();\n }\n };\n\n $timepicker.select = function(date, index, keep) {\n // console.warn('$timepicker.select', date, scope.$mode);\n if(!controller.$dateValue || isNaN(controller.$dateValue.getTime())) controller.$dateValue = new Date(1970, 0, 1);\n if(!angular.isDate(date)) date = new Date(date);\n if(index === 0) controller.$dateValue.setHours(date.getHours());\n else if(index === 1) controller.$dateValue.setMinutes(date.getMinutes());\n else if(index === 2) controller.$dateValue.setSeconds(date.getSeconds());\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $timepicker.hide(true); });\n }\n };\n\n $timepicker.switchMeridian = function(date) {\n if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) {\n return;\n }\n var hours = (date || controller.$dateValue).getHours();\n controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12);\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n };\n\n // Protected methods\n\n $timepicker.$build = function() {\n // console.warn('$timepicker.$build() viewDate=%o', viewDate);\n var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n var hours = [], hour;\n for(i = 0; i < options.length; i++) {\n hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);\n hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});\n }\n var minutes = [], minute;\n for(i = 0; i < options.length; i++) {\n minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);\n minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n }\n var seconds = [], second;\n for(i = 0; i < options.length; i++) {\n second = new Date(1970, 0, 1, 0, 0, viewDate.second - (midIndex - i) * options.secondStep);\n seconds.push({date: second, label: formatDate(second, secondsFormat), selected: $timepicker.$date && $timepicker.$isSelected(second, 2), disabled: $timepicker.$isDisabled(second, 2)});\n }\n\n var rows = [];\n for(i = 0; i < options.length; i++) {\n if (showSeconds) {\n rows.push([hours[i], minutes[i], seconds[i]]);\n } else {\n rows.push([hours[i], minutes[i]]);\n }\n }\n scope.rows = rows;\n scope.showSeconds = showSeconds;\n scope.showAM = showAM;\n scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n scope.timeSeparator = timeSeparator;\n $timepicker.$isBuilt = true;\n };\n\n $timepicker.$isSelected = function(date, index) {\n if(!$timepicker.$date) return false;\n else if(index === 0) {\n return date.getHours() === $timepicker.$date.getHours();\n } else if(index === 1) {\n return date.getMinutes() === $timepicker.$date.getMinutes();\n } else if(index === 2) {\n return date.getSeconds() === $timepicker.$date.getSeconds();\n }\n };\n\n $timepicker.$isDisabled = function(date, index) {\n var selectedTime;\n if(index === 0) {\n selectedTime = date.getTime() + viewDate.minute * 6e4 + viewDate.second * 1e3;\n } else if(index === 1) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.second * 1e3;\n } else if(index === 2) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.minute * 6e4;\n }\n return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1;\n };\n\n scope.$arrowAction = function (value, index) {\n if (options.arrowBehavior === 'picker') {\n $timepicker.$setTimeByStep(value,index);\n } else {\n $timepicker.$moveIndex(value,index);\n }\n };\n\n $timepicker.$setTimeByStep = function(value, index) {\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n if (index === 0) {\n newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n }\n else if (index === 1) {\n newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\n }\n else if (index === 2) {\n newDate.setSeconds(seconds - (parseInt(options.secondStep, 10) * value));\n }\n $timepicker.select(newDate, index, true);\n };\n\n $timepicker.$moveIndex = function(value, index) {\n var targetDate;\n if(index === 0) {\n targetDate = new Date(1970, 0, 1, viewDate.hour + (value * options.length), viewDate.minute, viewDate.second);\n angular.extend(viewDate, {hour: targetDate.getHours()});\n } else if(index === 1) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + (value * options.length * options.minuteStep), viewDate.second);\n angular.extend(viewDate, {minute: targetDate.getMinutes()});\n } else if(index === 2) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute, viewDate.second + (value * options.length * options.secondStep));\n angular.extend(viewDate, {second: targetDate.getSeconds()});\n }\n $timepicker.$build();\n };\n\n $timepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n if(evt.target.nodeName.toLowerCase() !== 'input') evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $timepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Close on enter\n if(evt.keyCode === 13) return $timepicker.hide(true);\n\n // Navigate with keyboard\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n var sepLength = 1;\n var lateralMove = /(37|39)/.test(evt.keyCode);\n var count = 2 + showSeconds * 1 + showAM * 1;\n\n // Navigate indexes (left, right)\n if (lateralMove) {\n if(evt.keyCode === 37) selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1;\n else if(evt.keyCode === 39) selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0;\n }\n\n // Update values (up, down)\n var selectRange = [0, hoursLength];\n var incr = 0;\n if (evt.keyCode === 38) incr = -1;\n if (evt.keyCode === 40) incr = +1;\n var isSeconds = selectedIndex === 2 && showSeconds;\n var isMeridian = selectedIndex === 2 && !showSeconds || selectedIndex === 3 && showSeconds;\n if(selectedIndex === 0) {\n newDate.setHours(hours + incr*parseInt(options.hourStep, 10));\n // re-calculate hours length because we have changed hours value\n hoursLength = formatDate(newDate, hoursFormat).length;\n selectRange = [0, hoursLength];\n } else if(selectedIndex === 1) {\n newDate.setMinutes(minutes + incr*parseInt(options.minuteStep, 10));\n // re-calculate minutes length because we have changes minutes value\n minutesLength = formatDate(newDate, minutesFormat).length;\n selectRange = [hoursLength + sepLength, minutesLength];\n } else if(isSeconds) {\n newDate.setSeconds(seconds + incr*parseInt(options.secondStep, 10));\n // re-calculate seconds length because we have changes seconds value\n secondsLength = formatDate(newDate, secondsFormat).length;\n selectRange = [hoursLength + sepLength + minutesLength + sepLength, secondsLength];\n } else if(isMeridian) {\n if(!lateralMove) $timepicker.switchMeridian();\n selectRange = [hoursLength + sepLength + minutesLength + sepLength + (secondsLength + sepLength)*showSeconds, 2];\n }\n $timepicker.select(newDate, selectedIndex, true);\n createSelection(selectRange[0], selectRange[1]);\n parentScope.$digest();\n };\n\n // Private\n\n function createSelection(start, length) {\n var end = start + length;\n if(element[0].createTextRange) {\n var selRange = element[0].createTextRange();\n selRange.collapse(true);\n selRange.moveStart('character', start);\n selRange.moveEnd('character', end);\n selRange.select();\n } else if(element[0].setSelectionRange) {\n element[0].setSelectionRange(start, end);\n } else if(angular.isUndefined(element[0].selectionStart)) {\n element[0].selectionStart = start;\n element[0].selectionEnd = end;\n }\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $timepicker.init;\n $timepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'time');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $timepicker.destroy;\n $timepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $timepicker.show;\n $timepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $timepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $timepicker.hide;\n $timepicker.hide = function(blur) {\n if(!$timepicker.$isShown) return;\n $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $timepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $timepicker;\n\n }\n\n timepickerFactory.defaults = defaults;\n return timepickerFactory;\n\n };\n\n })\n\n\n .directive('bsTimepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n var defaults = $timepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'timeType', 'timeFormat', 'timezone', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'secondStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'roundDisplay', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative', 'roundDisplay'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!timepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(timepicker),?/i);\n newValue === true ? timepicker.show() : timepicker.hide();\n });\n\n // Initialize timepicker\n if(isNative && (options.useNative || defaults.useNative)) options.timeFormat = 'HH:mm';\n var timepicker = $timepicker(element, controller, options);\n options = timepicker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n // Initialize parser\n var dateParser = $dateParser({format: options.timeFormat, lang: lang});\n\n // Observe attributes for changes\n angular.forEach(['minTime', 'maxTime'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n !isNaN(timepicker.$options[key]) && timepicker.$build();\n validateAgainstMinMaxTime(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue);\n timepicker.update(controller.$dateValue);\n }, true);\n\n function validateAgainstMinMaxTime(parsedTime) {\n if (!angular.isDate(parsedTime)) return;\n var isMinValid = isNaN(options.minTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) >= options.minTime;\n var isMaxValid = isNaN(options.maxTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) <= options.maxTime;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(!isValid) {\n return;\n }\n controller.$dateValue = parsedTime;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n controller.$setValidity('date', true);\n return null;\n }\n var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedTime || isNaN(parsedTime.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxTime(parsedTime);\n }\n\n if(options.timeType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedTime, options.timezone, true);\n return formatDate(date, options.modelTimeFormat || options.timeFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.timeType === 'number') {\n return date.getTime();\n } else if(options.timeType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.timeType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.timeType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelTimeFormat);\n } else if(options.timeType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5);\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getTimeFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getTimeFormattedString());\n };\n\n function getTimeFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (timepicker) timepicker.destroy();\n options = null;\n timepicker = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.tab', [])\n\n .provider('$tab', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n template: 'tab/tab.tpl.html',\n navClass: 'nav-tabs',\n activeClass: 'active'\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'navClass', 'activeClass'], function(key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // Publish options on scope\n $scope.$navClass = self.$options.navClass;\n $scope.$activeClass = self.$options.activeClass;\n\n self.$panes = $scope.$panes = [];\n\n // Please use $activePaneChangeListeners if you use `bsActivePane`\n // Because we removed `ngModel` as default, we rename viewChangeListeners to\n // activePaneChangeListeners to make more sense.\n self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var activeIndex = self.$panes.$active;\n\n // remove pane from $panes array\n self.$panes.splice(index, 1);\n\n if (index < activeIndex) {\n // we removed a pane before the active pane, so we need to\n // decrement the active pane index\n activeIndex--;\n }\n else if (index === activeIndex && activeIndex === self.$panes.length) {\n // we remove the active pane and it was the one at the end,\n // so select the previous one\n activeIndex--;\n }\n self.$setActive(activeIndex);\n };\n\n self.$panes.$active = 0;\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$activePaneChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n };\n\n this.$get = function() {\n var $tab = {};\n $tab.defaults = defaults;\n $tab.controller = controller;\n return $tab;\n };\n\n })\n\n .directive('bsTabs', function($window, $animate, $tab, $parse) {\n\n var defaults = $tab.defaults;\n\n return {\n require: ['?ngModel', 'bsTabs'],\n transclude: true,\n scope: true,\n controller: ['$scope', '$element', '$attrs', $tab.controller],\n templateUrl: function(element, attr) {\n return attr.template || defaults.template;\n },\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // 'ngModel' does interfere with form validation\n // and status, use `bsActivePane` instead to avoid it\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n bsTabsCtrl.$setActive(modelValue * 1);\n return modelValue;\n });\n\n }\n\n if (attrs.bsActivePane) {\n // adapted from angularjs ngModelController bindings\n // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n // Update bsActivePane value with change\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n });\n\n // watch bsActivePane for value changes\n scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n bsTabsCtrl.$setActive(newValue * 1);\n }, true);\n }\n }\n };\n\n })\n\n .directive('bsPane', function($window, $animate, $sce) {\n\n return {\n require: ['^?ngModel', '^bsTabs'],\n scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // Add base class\n element.addClass('tab-pane');\n\n // Observe title attribute for change\n attrs.$observe('title', function(newValue, oldValue) {\n scope.title = $sce.trustAsHtml(newValue);\n });\n\n // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\n }\n\n attrs.$observe('disabled', function(newValue, oldValue) {\n scope.disabled = scope.$eval(newValue);\n });\n\n // Push pane to parent bsTabs controller\n bsTabsCtrl.$push(scope);\n\n // remove pane from tab controller when pane is destroyed\n scope.$on('$destroy', function() {\n bsTabsCtrl.$remove(scope);\n });\n\n function render() {\n var index = bsTabsCtrl.$panes.indexOf(scope);\n var active = bsTabsCtrl.$panes.$active;\n $animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$tooltip', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n prefixClass: 'tooltip',\n prefixEvent: 'tooltip',\n container: false,\n target: false,\n placement: 'top',\n template: 'tooltip/tooltip.tpl.html',\n contentTemplate: false,\n trigger: 'hover focus',\n keyboard: false,\n html: false,\n show: false,\n title: '',\n type: '',\n delay: 0,\n autoClose: false,\n bsEnabled: true,\n viewport: {\n selector: 'body',\n padding: 0\n }\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n var trim = String.prototype.trim;\n var isTouch = 'createTouch' in $window.document;\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n var $body = angular.element($window.document);\n\n function TooltipFactory(element, config) {\n\n var $tooltip = {};\n\n // Common vars\n var nodeName = element[0].nodeName.toLowerCase();\n var options = $tooltip.$options = angular.extend({}, defaults, config);\n $tooltip.$promise = fetchTemplate(options.template);\n var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(options.delay && angular.isString(options.delay)) {\n var split = options.delay.split(',').map(parseFloat);\n options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $tooltip.$id = options.id || element.attr('id') || '';\n\n // Support scope as string options\n if(options.title) {\n scope.title = $sce.trustAsHtml(options.title);\n }\n\n // Provide scope helpers\n scope.$setEnabled = function(isEnabled) {\n scope.$$postDigest(function() {\n $tooltip.setEnabled(isEnabled);\n });\n };\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $tooltip.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $tooltip.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $tooltip.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $tooltip.$isShown = scope.$isShown = false;\n\n // Private vars\n var timeout, hoverState;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $tooltip.$promise = $tooltip.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]);\n if(!contentEl.length) contentEl = findElement('[ng-bind=\"title\"]', templateEl[0]);\n contentEl.removeAttr('ng-bind').html(contentTemplate);\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize tooltip\n var tipLinker, tipElement, tipTemplate, tipContainer, tipScope;\n $tooltip.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n tipTemplate = template;\n tipLinker = $compile(template);\n $tooltip.init();\n });\n\n $tooltip.init = function() {\n\n // Options: delay\n if (options.delay && angular.isNumber(options.delay)) {\n options.delay = {\n show: options.delay,\n hide: options.delay\n };\n }\n\n // Replace trigger on touch devices ?\n // if(isTouch && options.trigger === defaults.trigger) {\n // options.trigger.replace(/hover/g, 'click');\n // }\n\n // Options : container\n if(options.container === 'self') {\n tipContainer = element;\n } else if(angular.isElement(options.container)) {\n tipContainer = options.container;\n } else if(options.container) {\n tipContainer = findElement(options.container);\n }\n\n // Options: trigger\n bindTriggerEvents();\n\n // Options: target\n if(options.target) {\n options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n }\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n options.trigger === 'focus' ? element[0].focus() : $tooltip.show();\n });\n }\n\n };\n\n $tooltip.destroy = function() {\n\n // Unbind events\n unbindTriggerEvents();\n\n // Remove element\n destroyTipElement();\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $tooltip.enter = function() {\n\n clearTimeout(timeout);\n hoverState = 'in';\n if (!options.delay || !options.delay.show) {\n return $tooltip.show();\n }\n\n timeout = setTimeout(function() {\n if (hoverState ==='in') $tooltip.show();\n }, options.delay.show);\n\n };\n\n $tooltip.show = function() {\n if (!options.bsEnabled || $tooltip.$isShown) return;\n\n scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n var parent, after;\n if (options.container) {\n parent = tipContainer;\n if (tipContainer[0].lastChild) {\n after = angular.element(tipContainer[0].lastChild);\n } else {\n after = null;\n }\n } else {\n parent = null;\n after = element;\n }\n\n\n // Hide any existing tipElement\n if(tipElement) destroyTipElement();\n // Fetch a cloned element linked from template\n tipScope = $tooltip.$scope.$new();\n tipElement = $tooltip.$element = tipLinker(tipScope, function(clonedElement, scope) {});\n\n // Set the initial positioning. Make the tooltip invisible\n // so IE doesn't try to focus on it off screen.\n tipElement.css({top: '-9999px', left: '-9999px', right: 'auto', display: 'block', visibility: 'hidden'});\n\n // Options: animation\n if(options.animation) tipElement.addClass(options.animation);\n // Options: type\n if(options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n // Options: custom classes\n if(options.customClass) tipElement.addClass(options.customClass);\n\n // Append the element, without any animations. If we append\n // using $animate.enter, some of the animations cause the placement\n // to be off due to the transforms.\n after ? after.after(tipElement) : parent.prepend(tipElement);\n\n $tooltip.$isShown = scope.$isShown = true;\n safeDigest(scope);\n\n // Now, apply placement\n $tooltip.$applyPlacement();\n\n // Once placed, animate it.\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.enter(tipElement, parent, after, enterAnimateCallback);\n if(promise && promise.then) promise.then(enterAnimateCallback);\n safeDigest(scope);\n\n $$rAF(function () {\n // Once the tooltip is placed and the animation starts, make the tooltip visible\n if(tipElement) tipElement.css({visibility: 'visible'});\n });\n\n // Bind events\n if(options.keyboard) {\n if(options.trigger !== 'focus') {\n $tooltip.focus();\n }\n bindKeyboardEvents();\n }\n\n if(options.autoClose) {\n bindAutoCloseEvents();\n }\n\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $tooltip);\n }\n\n $tooltip.leave = function() {\n\n clearTimeout(timeout);\n hoverState = 'out';\n if (!options.delay || !options.delay.hide) {\n return $tooltip.hide();\n }\n timeout = setTimeout(function () {\n if (hoverState === 'out') {\n $tooltip.hide();\n }\n }, options.delay.hide);\n\n };\n\n var _blur;\n var _tipToHide;\n $tooltip.hide = function(blur) {\n\n if(!$tooltip.$isShown) return;\n scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n\n // store blur value for leaveAnimateCallback to use\n _blur = blur;\n\n // store current tipElement reference to use\n // in leaveAnimateCallback\n _tipToHide = tipElement;\n\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.leave(tipElement, leaveAnimateCallback);\n if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n $tooltip.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.keyboard && tipElement !== null) {\n unbindKeyboardEvents();\n }\n\n if(options.autoClose && tipElement !== null) {\n unbindAutoCloseEvents();\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\n\n // check if current tipElement still references\n // the same element when hide was called\n if (tipElement === _tipToHide) {\n // Allow to blur the input when hidden, like when pressing enter key\n if(_blur && options.trigger === 'focus') {\n return element[0].blur();\n }\n\n // clean up child scopes\n destroyTipElement();\n }\n }\n\n $tooltip.toggle = function() {\n $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter();\n };\n\n $tooltip.focus = function() {\n tipElement[0].focus();\n };\n\n $tooltip.setEnabled = function(isEnabled) {\n options.bsEnabled = isEnabled;\n };\n\n $tooltip.setViewport = function(viewport) {\n options.viewport = viewport;\n };\n\n // Protected methods\n\n $tooltip.$applyPlacement = function() {\n if(!tipElement) return;\n\n // Determine if we're doing an auto or normal placement\n var placement = options.placement,\n autoToken = /\\s?auto?\\s?/i,\n autoPlace = autoToken.test(placement);\n\n if (autoPlace) {\n placement = placement.replace(autoToken, '') || defaults.placement;\n }\n\n // Need to add the position class before we get\n // the offsets\n tipElement.addClass(options.placement);\n\n // Get the position of the target element\n // and the height and width of the tooltip so we can center it.\n var elementPosition = getPosition(),\n tipWidth = tipElement.prop('offsetWidth'),\n tipHeight = tipElement.prop('offsetHeight');\n\n // If we're auto placing, we need to check the positioning\n if (autoPlace) {\n var originalPlacement = placement;\n var container = options.container ? findElement(options.container) : element.parent();\n var containerPosition = getPosition(container);\n\n // Determine if the vertical placement\n if (originalPlacement.indexOf('bottom') >= 0 && elementPosition.bottom + tipHeight > containerPosition.bottom) {\n placement = originalPlacement.replace('bottom', 'top');\n } else if (originalPlacement.indexOf('top') >= 0 && elementPosition.top - tipHeight < containerPosition.top) {\n placement = originalPlacement.replace('top', 'bottom');\n }\n\n // Determine the horizontal placement\n // The exotic placements of left and right are opposite of the standard placements. Their arrows are put on the left/right\n // and flow in the opposite direction of their placement.\n if ((originalPlacement === 'right' || originalPlacement === 'bottom-left' || originalPlacement === 'top-left') &&\n elementPosition.right + tipWidth > containerPosition.width) {\n\n placement = originalPlacement === 'right' ? 'left' : placement.replace('left', 'right');\n } else if ((originalPlacement === 'left' || originalPlacement === 'bottom-right' || originalPlacement === 'top-right') &&\n elementPosition.left - tipWidth < containerPosition.left) {\n\n placement = originalPlacement === 'left' ? 'right' : placement.replace('right', 'left');\n }\n\n tipElement.removeClass(originalPlacement).addClass(placement);\n }\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n applyPlacement(tipPosition, placement);\n };\n\n $tooltip.$onKeyUp = function(evt) {\n if (evt.which === 27 && $tooltip.$isShown) {\n $tooltip.hide();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusKeyUp = function(evt) {\n if (evt.which === 27) {\n element[0].blur();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusElementMouseDown = function(evt) {\n evt.preventDefault();\n evt.stopPropagation();\n // Some browsers do not auto-focus buttons (eg. Safari)\n $tooltip.$isShown ? element[0].blur() : element[0].focus();\n };\n\n // bind/unbind events\n function bindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n angular.forEach(triggers, function(trigger) {\n if(trigger === 'click') {\n element.on('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n });\n }\n\n function unbindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n for (var i = triggers.length; i--;) {\n var trigger = triggers[i];\n if(trigger === 'click') {\n element.off('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n }\n }\n\n function bindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.on('keyup', $tooltip.$onKeyUp);\n } else {\n element.on('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n function unbindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.off('keyup', $tooltip.$onKeyUp);\n } else {\n element.off('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n var _autoCloseEventsBinded = false;\n function bindAutoCloseEvents() {\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // Stop propagation when clicking inside tooltip\n tipElement.on('click', stopEventPropagation);\n\n // Hide when clicking outside tooltip\n $body.on('click', $tooltip.hide);\n\n _autoCloseEventsBinded = true;\n }, 0, false);\n }\n\n function unbindAutoCloseEvents() {\n if (_autoCloseEventsBinded) {\n tipElement.off('click', stopEventPropagation);\n $body.off('click', $tooltip.hide);\n _autoCloseEventsBinded = false;\n }\n }\n\n function stopEventPropagation(event) {\n event.stopPropagation();\n }\n\n // Private methods\n\n function getPosition($element) {\n $element = $element || (options.target || element);\n\n var el = $element[0],\n isBody = el.tagName === 'BODY';\n\n var elRect = el.getBoundingClientRect();\n var rect = {};\n\n // IE8 has issues with angular.extend and using elRect directly.\n // By coping the values of elRect into a new object, we can continue to use extend\n for (var p in elRect) {\n // DO NOT use hasOwnProperty when inspecting the return of getBoundingClientRect.\n rect[p] = elRect[p];\n }\n\n if (rect.width === null) {\n // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n rect = angular.extend({}, rect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });\n }\n var elOffset = isBody ? { top: 0, left: 0 } : dimensions.offset(el),\n scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.prop('scrollTop') || 0 },\n outerDims = isBody ? { width: document.documentElement.clientWidth, height: $window.innerHeight } : null;\n\n return angular.extend({}, rect, scroll, outerDims, elOffset);\n }\n\n function getCalculatedOffset(placement, position, actualWidth, actualHeight) {\n var offset;\n var split = placement.split('-');\n\n switch (split[0]) {\n case 'right':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left + position.width\n };\n break;\n case 'bottom':\n offset = {\n top: position.top + position.height,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n case 'left':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left - actualWidth\n };\n break;\n default:\n offset = {\n top: position.top - actualHeight,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n }\n\n if(!split[1]) {\n return offset;\n }\n\n // Add support for corners @todo css\n if(split[0] === 'top' || split[0] === 'bottom') {\n switch (split[1]) {\n case 'left':\n offset.left = position.left;\n break;\n case 'right':\n offset.left = position.left + position.width - actualWidth;\n }\n } else if(split[0] === 'left' || split[0] === 'right') {\n switch (split[1]) {\n case 'top':\n offset.top = position.top - actualHeight;\n break;\n case 'bottom':\n offset.top = position.top + position.height;\n }\n }\n\n return offset;\n }\n\n function applyPlacement(offset, placement) {\n var tip = tipElement[0],\n width = tip.offsetWidth,\n height = tip.offsetHeight;\n\n // manually read margins because getBoundingClientRect includes difference\n var marginTop = parseInt(dimensions.css(tip, 'margin-top'), 10),\n marginLeft = parseInt(dimensions.css(tip, 'margin-left'), 10);\n\n // we must check for NaN for ie 8/9\n if (isNaN(marginTop)) marginTop = 0;\n if (isNaN(marginLeft)) marginLeft = 0;\n\n offset.top = offset.top + marginTop;\n offset.left = offset.left + marginLeft;\n\n // dimensions setOffset doesn't round pixel values\n // so we use setOffset directly with our own function\n dimensions.setOffset(tip, angular.extend({\n using: function (props) {\n tipElement.css({\n top: Math.round(props.top) + 'px',\n left: Math.round(props.left) + 'px',\n right: ''\n });\n }\n }, offset), 0);\n\n // check to see if placing tip in new offset caused the tip to resize itself\n var actualWidth = tip.offsetWidth,\n actualHeight = tip.offsetHeight;\n\n if (placement === 'top' && actualHeight !== height) {\n offset.top = offset.top + height - actualHeight;\n }\n\n // If it's an exotic placement, exit now instead of\n // applying a delta and changing the arrow\n if (/top-left|top-right|bottom-left|bottom-right/.test(placement)) return;\n\n var delta = getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);\n\n if (delta.left) {\n offset.left += delta.left;\n } else {\n offset.top += delta.top;\n }\n\n dimensions.setOffset(tip, offset);\n\n if (/top|right|bottom|left/.test(placement)) {\n var isVertical = /top|bottom/.test(placement),\n arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight,\n arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';\n\n replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical);\n }\n }\n\n function getViewportAdjustedDelta(placement, position, actualWidth, actualHeight) {\n var delta = { top: 0, left: 0 },\n $viewport = options.viewport && findElement(options.viewport.selector || options.viewport);\n\n if (!$viewport) {\n return delta;\n }\n\n var viewportPadding = options.viewport && options.viewport.padding || 0,\n viewportDimensions = getPosition($viewport);\n\n if (/right|left/.test(placement)) {\n var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll,\n bottomEdgeOffset = position.top + viewportPadding - viewportDimensions.scroll + actualHeight;\n if (topEdgeOffset < viewportDimensions.top) { // top overflow\n delta.top = viewportDimensions.top - topEdgeOffset;\n } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;\n }\n } else {\n var leftEdgeOffset = position.left - viewportPadding,\n rightEdgeOffset = position.left + viewportPadding + actualWidth;\n if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n delta.left = viewportDimensions.left - leftEdgeOffset;\n } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow\n delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;\n }\n }\n\n return delta;\n }\n\n function replaceArrow(delta, dimension, isHorizontal) {\n var $arrow = findElement('.tooltip-arrow, .arrow', tipElement[0]);\n\n $arrow.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')\n .css(isHorizontal ? 'top' : 'left', '');\n }\n\n function destroyTipElement() {\n // Cancel pending callbacks\n clearTimeout(timeout);\n\n if($tooltip.$isShown && tipElement !== null) {\n if(options.autoClose) {\n unbindAutoCloseEvents();\n }\n\n if(options.keyboard) {\n unbindKeyboardEvents();\n }\n }\n\n if(tipScope) {\n tipScope.$destroy();\n tipScope = null;\n }\n\n if(tipElement) {\n tipElement.remove();\n tipElement = $tooltip.$element = null;\n }\n }\n\n return $tooltip;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return TooltipFactory;\n\n };\n\n })\n\n .directive('bsTooltip', function($window, $location, $sce, $tooltip, $$rAF) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Observe scope attributes for change\n attr.$observe('title', function(newValue) {\n if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n var oldValue = scope.title;\n scope.title = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }\n });\n\n // Support scope as an object\n attr.bsTooltip && scope.$watch(attr.bsTooltip, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.title = newValue;\n }\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n newValue === true ? tooltip.show() : tooltip.hide();\n });\n\n // Enabled binding support\n attr.bsEnabled && scope.$watch(attr.bsEnabled, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n newValue === false ? tooltip.setEnabled(false) : tooltip.setEnabled(true);\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n tooltip.setViewport(newValue);\n });\n\n // Initialize popover\n var tooltip = $tooltip(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(tooltip) tooltip.destroy();\n options = null;\n tooltip = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$typeahead', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'typeahead',\n prefixEvent: '$typeahead',\n placement: 'bottom-left',\n template: 'typeahead/typeahead.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n minLength: 1,\n filter: 'filter',\n limit: 6,\n autoSelect: false,\n comparator: '',\n trimValue: true\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n\n function TypeaheadFactory(element, controller, config) {\n\n var $typeahead = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $typeahead = $tooltip(element, options);\n var parentScope = config.scope;\n var scope = $typeahead.$scope;\n\n scope.$resetMatches = function(){\n scope.$matches = [];\n scope.$activeIndex = options.autoSelect ? 0 : -1; // If set to 0, the first match will be highlighted\n };\n scope.$resetMatches();\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $typeahead.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $typeahead.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $typeahead.$isVisible();\n };\n\n // Public methods\n\n $typeahead.update = function(matches) {\n scope.$matches = matches;\n if(scope.$activeIndex >= matches.length) {\n scope.$activeIndex = options.autoSelect ? 0: -1;\n }\n\n // When the placement is not one of the bottom placements, re-calc the positioning\n // so the results render correctly.\n if (/^(bottom|bottom-left|bottom-right)$/.test(options.placement)) return;\n\n // wrap in a $timeout so the results are updated\n // before repositioning\n $timeout($typeahead.$applyPlacement);\n };\n\n $typeahead.activate = function(index) {\n scope.$activeIndex = index;\n };\n\n $typeahead.select = function(index) {\n if(index === -1) return;\n var value = scope.$matches[index].value;\n // console.log('$setViewValue', value);\n controller.$setViewValue(value);\n controller.$render();\n scope.$resetMatches();\n if(parentScope) parentScope.$digest();\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $typeahead);\n };\n\n // Protected methods\n\n $typeahead.$isVisible = function() {\n if(!options.minLength || !controller) {\n return !!scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength;\n };\n\n $typeahead.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $typeahead.$onMouseDown = function(evt) {\n // Prevent blur on mousedown\n evt.preventDefault();\n evt.stopPropagation();\n };\n\n $typeahead.$onKeyDown = function(evt) {\n if(!/(38|40|13)/.test(evt.keyCode)) return;\n\n // Let ngSubmit pass if the typeahead tip is hidden or no option is selected\n if($typeahead.$isVisible() && !(evt.keyCode === 13 && scope.$activeIndex === -1)) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n // Select with enter\n if(evt.keyCode === 13 && scope.$matches.length) {\n $typeahead.select(scope.$activeIndex);\n }\n\n // Navigate with keyboard\n else if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n };\n\n // Overrides\n\n var show = $typeahead.show;\n $typeahead.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $typeahead.$onKeyDown);\n }\n }, 0, false);\n };\n\n var hide = $typeahead.hide;\n $typeahead.hide = function() {\n $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $typeahead.$onKeyDown);\n }\n if(!options.autoSelect)\n $typeahead.activate(-1);\n hide();\n };\n\n return $typeahead;\n\n }\n\n TypeaheadFactory.defaults = defaults;\n return TypeaheadFactory;\n\n };\n\n })\n\n .directive('bsTypeahead', function($window, $parse, $q, $typeahead, $parseOptions) {\n\n var defaults = $typeahead.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'filter', 'limit', 'minLength', 'watchOptions', 'selectMode', 'autoSelect', 'comparator', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'trimValue'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n });\n\n // Disable browser autocompletion\n element.attr('autocomplete' ,'off');\n\n // Build proper bsOptions\n var filter = options.filter || defaults.filter;\n var limit = options.limit || defaults.limit;\n var comparator = options.comparator || defaults.comparator;\n\n var bsOptions = attr.bsOptions;\n if(filter) bsOptions += ' | ' + filter + ':$viewValue';\n if (comparator) bsOptions += ':' + comparator;\n if(limit) bsOptions += ' | limitTo:' + limit;\n var parsedOptions = $parseOptions(bsOptions);\n\n // Initialize typeahead\n var typeahead = $typeahead(element, controller, options);\n\n // Watch options on demand\n if(options.watchOptions) {\n // Watch bsOptions values before filtering for changes, drop function calls\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n scope.$watchCollection(watchedOptions, function (newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller).then(function (values) {\n typeahead.update(values);\n controller.$render();\n });\n });\n }\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('$watch', element.attr('ng-model'), newValue);\n scope.$modelValue = newValue; // Publish modelValue on scope for custom templates\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n // Prevent input with no future prospect if selectMode is truthy\n // @TODO test selectMode\n if(options.selectMode && !values.length && newValue.length > 0) {\n controller.$setViewValue(controller.$viewValue.substring(0, controller.$viewValue.length - 1));\n return;\n }\n if(values.length > limit) values = values.slice(0, limit);\n var isVisible = typeahead.$isVisible();\n isVisible && typeahead.update(values);\n // Do not re-queue an update if a correct value has been selected\n if(values.length === 1 && values[0].value === newValue) return;\n !isVisible && typeahead.update(values);\n // Queue a new rendering that will leverage collection loading\n controller.$render();\n });\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var displayValue = parsedOptions.displayValue(modelValue);\n return displayValue === undefined ? '' : displayValue;\n });\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n if(controller.$isEmpty(controller.$viewValue)) return element.val('');\n var index = typeahead.$getIndex(controller.$modelValue);\n var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;\n selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;\n var value = selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '') : '';\n element.val(options.trimValue === false ? value : value.trim());\n };\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (typeahead) typeahead.destroy();\n options = null;\n typeahead = null;\n });\n\n }\n };\n\n });\n"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["angular-strap.js","affix/affix.js","button/button.js","alert/alert.js","aside/aside.js","collapse/collapse.js","datepicker/datepicker.js","dropdown/dropdown.js","helpers/date-formatter.js","helpers/date-parser.js","helpers/debounce.js","helpers/dimensions.js","helpers/parse-options.js","helpers/raf.js","modal/modal.js","navbar/navbar.js","popover/popover.js","scrollspy/scrollspy.js","select/select.js","tab/tab.js","timepicker/timepicker.js","tooltip/tooltip.js","typeahead/typeahead.js"],"names":["window","document","undefined","angular","bodyEl","$window","body","windowEl","defaults","AffixFactory","offsetTop","$affix","inlineStyles","options","this","$get","reset","setWidth","initialAffixTop","offsetParent","match","getRequiredAffixClass","unpin","position","top","scrollTop","getScrollTop","scrollHeight","getScrollHeight","targetEl","pageYOffset","directive","parent","target","initialOffsetTop","offsetBottom","affixed","element","init","i","$parseOffsets","on","checkPosition","require","checkPositionWithEventLoop","dimensions","offset","destroy","style","width","off","affix","setTimeout","elementHeight","height","css","addClass","offsetUnpin","offsetHeight","offsetWidth","$debouncedOnResize","$onResize","initialPosition","restrict","affixTarget","$element","forEach","link","key","scope","option","$on","attr","test","controller","activeClass","toggleEvent","compile","children","querySelectorAll","childEl","ngModel","removeAttr","child","$button","constantValueRegExp","isInput","trueValue","falseValue","isDefined","hasExoticValues","viewValue","$formatters","push","$render","modelValue","isActive","equals","checked","activeElement","bind","$modelValue","$$rAF","$setViewValue","toggleClass","$apply","hasClass","$observe","value","nodeName","module","container","provider","backdrop","keyboard","show","duration","type","dismissable","AlertFactory","$alert","$scope","config","extend","$timeout","hide","falseValueRegExp","hasOwnProperty","title","newValue","oldValue","trustAsHtml","bsAlert","content","alert","trigger","toggle","animation","contentTemplate","html","AsideFactory","$aside","requestAnimationFrame","$modal","bsAside","$watch","aside","self","startCollapsed","allowMultiple","$attrs","activeIndexes","$targets","$active","length","index","indexOf","activeItems","splice","activateItem","$options","$collapse","copy","$toggles","$unregisterToggle","$registerToggle","$unregisterTarget","deactivateItem","$viewChangeListeners","fn","fixActiveItemIndexes","$setActive","disallowToggle","$activeIndexes","bsCollapseCtrl","controllers","$animate","ngModelCtrl","attrs","isArray","bsCollapseToggle","$registerTarget","render","active","action","prefixClass","delay","useNative","dateType","dateFormat","timezone","modelDateFormat","dayFormat","monthFormat","yearFormat","monthTitleFormat","yearTitleFormat","strictFormat","autoclose","minDate","Infinity","maxDate","startView","minView","startWeek","daysOfWeekDisabled","iconLeft","iconRight","isNative","DatepickerFactory","parentScope","$datepicker","pickerViews","views","el","selected","date","focus","viewDate","$iconLeft","$iconRight","$picker","$views","$mode","datepickerViews","$selectPane","$toggleMode","setMode","select","isDate","$build","updateDisabledDates","disabledDateRanges","dateRanges","$date","$dateValue","keep","Date","year","getFullYear","month","getDate","mode","pristine","call","$updateSelected","rows","built","$isSelected","$setDisabledEl","disabled","isDisabled","steps","targetDate","getUTCFullYear","getUTCMonth","UTC","$onMouseDown","evt","preventDefault","stopPropagation","isTouch","getUTCDate","$onKeyDown","keyCode","shiftKey","altKey","updateSelected","onKeyDown","$digest","prop","focusElement","_init","_destroy","_show","_hide","blur","previousValue","normalizeDateRanges","ranges","disabledRanges","datepicker","isMaxValid","isValid","isMinValid","isNaN","parsedDate","getTime","$parsers","unshift","$setValidity","getDateFormattedString","formatDate","bsShow","lang","format","$dateFormatter","dateParser","$dateParser","strict","validateAgainstMinMaxDate","getDateForAttribute","disabledDates","parse","timezoneOffsetAdjust","isUndefined","NaN","daySplit","arr","mod","n","m","arrays","size","$sce","weekDaysMin","weekdaysShort","weekDaysLabelsHtml","startDate","picker","weekDaysLabels","slice","concat","split","getMonth","update","firstDayOfMonth","firstDate","getDay","today","firstDateOffset","build","day","days","isToday","toDateString","label","muted","showLabels","labels","time","isSelected","newDate","name","firstMonth","months","lastDate","actualMonth","parseInt","firstYear","years","actualYear","setYear","placement","matchesSelector","DropdownFactory","$dropdown","onBodyClick","items","$rootScope","$new","parentEl","$isShown","removeClass","prototype","transclusion","bsDropdown","dropdown","isString","getDefaultLocale","id","splitTimeFormat","timeFormat","exec","DATETIME_FORMATS","$locale","getDatetimeFormat","SHORTDAY","hoursFormat","minutesFormat","secondsFormat","timeSeparator","showSeconds","dateFilter","ParseDate","seconds","$localeProvider","milliseconds","hours","array","isNumeric","parseFloat","isFinite","indexOfCaseInsensitive","len","str","toString","toLowerCase","DateParserFactory","minutes","getHours","getMilliseconds","getMinutes","proto","noop","toDate","regExpMap","sss","mm","keys","setFnMap","map","clonedFormat","search","v","sortedMap","regExpForFormat","re","join","text","replace","Object","escapeReservedSymbols","RegExp","regex","HH","H","hh","h","a","EEEE","EEE","dd","d","MMMM","MMM","SHORTMONTH","MM","M","DAY","yyyy","yy","y","MONTH","ss","setSeconds","s","setMinutes","setHours","setDate","setMonth","setFullYear","$format","baseDate","setMap","formatRegex","formatSetMap","setMapForFormat","matches","fromDate","substr","getTimeForAttribute","daylightSavingAdjust","undo","func","timeout","context","factory","immediate","apply","args","cancel","callNow","leading","trailing","wait","currentStyle","getComputedStyle","extra","boxRect","getBoundingClientRect","left","docElement","ownerDocument","curPosition","curLeft","curCSSTop","documentElement","clientTop","pageXOffset","scrollLeft","clientLeft","curCSSLeft","calculatePosition","curTop","curOffset","curElem","props","isFunction","using","offsetParentRect","offsetParentElement","outer","$parseOptions","$values","regexp","$match","displayFn","locals","valueName","valueFn","ParseOptionsFactory","groupByFn","valuesFn","$parse","keyName","cancelAnimationFrame","when","values","parseValues","raf","webkitRequestAnimationFrame","mozRequestAnimationFrame","rafSupported","timer","prefixEvent","template","trim","bodyElement","htmlReplaceRegExp","ModalFactory","enterAnimateCallback","promise","modalElement","leaveAnimateCallback","currentTarget","safeDigest","preventEventDefault","$hide","$$postDigest","$id","$show","$promise","templateEl","fetchTemplate","outerHTML","then","modalLinker","backdropElement","right","z-index","data","$compile","remove","$destroy","after","isElement","$emit","defaultPrevented","clonedElement","display","enter","hideOnBackdropClick","$onKeyUp","leave","which","fetchPromises","cache","$templateCache","res","$http","get","bsModal","modal","routeAttr","$navbar","liElements","li","liElement","pattern","path","autoClose","$popover","PopoverFactory","$tooltip","dataTarget","popover","bsPopover","isObject","$applyPlacement","setViewport","viewport","spies","$document","debounce","throttle","ScrollSpyFactory","scrollEl","isWindowSpy","scrollId","$$count","$scrollspy","unbindViewContentLoaded","unbindIncludeContentLoaded","trackedElements","$trackedElements","sortedElements","activeTarget","debouncedCheckPosition","viewportHeight","throttledCheckPosition","debouncedCheckOffsets","checkOffsets","docEl","$activateElement","source","$getTrackedElement","filter","targetElement","querySelector","trackedElement","b","trackElement","toDelete","untrackElement","activate","scrollspy","multiple","allNoneButtons","sort","caretHtml","placeholder","allText","noneText","maxLength","maxLengthHtml","iconCheckmark","SelectFactory","$select","$activeIndex","$isMultiple","$showAllNoneButtons","$allText","$iconCheckmark","$isActive","$isVisible","$selectNone","$matches","$updateActiveIndex","$getIndex","minLength","$viewValue","l","dataMultiple","inputEl","watchedOptions","$watchCollection","parsedOptions","bsOptions","$isEmpty","navClass","$activeClass","$panes","$activePaneChangeListeners","$push","pane","$navClass","$remove","activeIndex","$pane","$tab","transclude","templateUrl","postLink","bsTabsCtrl","bsActivePane","parsedBsActivePane","assign","timeType","modelTimeFormat","minTime","maxTime","hourStep","minuteStep","secondStep","roundDisplay","iconUp","iconDown","arrowBehavior","timepickerFactory","hour","meridian","coeff","selRange","end","start","setSelectionRange","collapse","selectionStart","moveStart","selectionEnd","moveEnd","$timepicker","floorMinutes","floor","selectedIndex","defaultDate","second","getSeconds","millisecond","$iconUp","$iconDown","$moveIndex","$switchMeridian","switchMeridian","minute","midIndex","$isDisabled","showAM","isAM","selectedTime","$arrowAction","$setTimeByStep","hoursLength","triggerHandler","secondsLength","sepLength","lateralMove","count","minutesLength","selectRange","incr","isSeconds","isMeridian","createSelection","createTextRange","parsedTime","getTimeFormattedString","timepicker","validateAgainstMinMaxTime","bsEnabled","selector","padding","String","$body","_tipToHide","tipElement","triggers","unbindTriggerEvents","bindKeyboardEvents","$onFocusElementMouseDown","unbindKeyboardEvents","_autoCloseEventsBinded","bindAutoCloseEvents","unbindAutoCloseEvents","stopEventPropagation","event","getPosition","rect","elRect","p","scroll","isBody","getCalculatedOffset","actualWidth","actualHeight","outerDims","clientWidth","innerHeight","tip","marginTop","marginLeft","setOffset","delta","getViewportAdjustedDelta","isVertical","replaceArrow","arrowDelta","arrowOffsetPosition","viewportPadding","topEdgeOffset","$viewport","viewportDimensions","leftEdgeOffset","rightEdgeOffset","dimension","isHorizontal","findElement","$arrow","clearTimeout","tipScope","$$phase","$setEnabled","setEnabled","isEnabled","contentEl","tipLinker","tipTemplate","isNumber","tipContainer","bindTriggerEvents","destroyTipElement","hoverState","lastChild","visibility","prepend","_blur","elementPosition","autoPlace","originalPlacement","containerPosition","tipHeight","tipPosition","applyPlacement","tipWidth","TooltipFactory","$location","tooltip","bsTooltip","limit","autoSelect","comparator","trimValue","$typeahead","$resetMatches","TypeaheadFactory","typeahead","watchOptions","selectMode","isVisible","displayValue","val"],"mappings":"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","file":"angular-strap.min.js","sourcesContent":["(function(window, document, undefined) {\n'use strict';\n\n// Source: module.js\nangular.module('mgcrea.ngStrap', [\n 'mgcrea.ngStrap.modal',\n 'mgcrea.ngStrap.aside',\n 'mgcrea.ngStrap.alert',\n 'mgcrea.ngStrap.button',\n 'mgcrea.ngStrap.select',\n 'mgcrea.ngStrap.datepicker',\n 'mgcrea.ngStrap.timepicker',\n 'mgcrea.ngStrap.navbar',\n 'mgcrea.ngStrap.tooltip',\n 'mgcrea.ngStrap.popover',\n 'mgcrea.ngStrap.dropdown',\n 'mgcrea.ngStrap.typeahead',\n 'mgcrea.ngStrap.scrollspy',\n 'mgcrea.ngStrap.affix',\n 'mgcrea.ngStrap.tab',\n 'mgcrea.ngStrap.collapse'\n]);\n\n// Source: affix/affix.js\nangular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mgcrea.ngStrap.helpers.debounce'])\n\n .provider('$affix', function() {\n\n var defaults = this.defaults = {\n offsetTop: 'auto',\n inlineStyles: true\n };\n\n this.$get = function($window, debounce, dimensions) {\n\n var bodyEl = angular.element($window.document.body);\n var windowEl = angular.element($window);\n\n function AffixFactory(element, config) {\n\n var $affix = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var targetEl = options.target;\n\n // Initial private vars\n var reset = 'affix affix-top affix-bottom',\n setWidth = false,\n initialAffixTop = 0,\n initialOffsetTop = 0,\n offsetTop = 0,\n offsetBottom = 0,\n affixed = null,\n unpin = null;\n\n var parent = element.parent();\n // Options: custom parent\n if (options.offsetParent) {\n if (options.offsetParent.match(/^\\d+$/)) {\n for (var i = 0; i < (options.offsetParent * 1) - 1; i++) {\n parent = parent.parent();\n }\n }\n else {\n parent = angular.element(options.offsetParent);\n }\n }\n\n $affix.init = function() {\n\n this.$parseOffsets();\n initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n setWidth = !element[0].style.width;\n\n // Bind events\n targetEl.on('scroll', this.checkPosition);\n targetEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', this.$debouncedOnResize);\n\n // Both of these checkPosition() calls are necessary for the case where\n // the user hits refresh after scrolling to the bottom of the page.\n this.checkPosition();\n this.checkPositionWithEventLoop();\n\n };\n\n $affix.destroy = function() {\n\n // Unbind events\n targetEl.off('scroll', this.checkPosition);\n targetEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', this.$debouncedOnResize);\n\n };\n\n $affix.checkPositionWithEventLoop = function() {\n\n // IE 9 throws an error if we use 'this' instead of '$affix'\n // in this setTimeout call\n setTimeout($affix.checkPosition, 1);\n\n };\n\n $affix.checkPosition = function() {\n // if (!this.$element.is(':visible')) return\n\n var scrollTop = getScrollTop();\n var position = dimensions.offset(element[0]);\n var elementHeight = dimensions.height(element[0]);\n\n // Get required affix class according to position\n var affix = getRequiredAffixClass(unpin, position, elementHeight);\n\n // Did affix status changed this last check?\n if(affixed === affix) return;\n affixed = affix;\n\n // Add proper affix class\n element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\n\n if(affix === 'top') {\n unpin = null;\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', '');\n }\n } else if(affix === 'bottom') {\n if (options.offsetUnpin) {\n unpin = -(options.offsetUnpin * 1);\n }\n else {\n // Calculate unpin threshold when affixed to bottom.\n // Hopefully the browser scrolls pixel by pixel.\n unpin = position.top - scrollTop;\n }\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n }\n } else { // affix === 'middle'\n unpin = null;\n if(setWidth) {\n element.css('width', element[0].offsetWidth + 'px');\n }\n if (options.inlineStyles) {\n element.css('position', 'fixed');\n element.css('top', initialAffixTop + 'px');\n }\n }\n\n };\n\n $affix.$onResize = function() {\n $affix.$parseOffsets();\n $affix.checkPosition();\n };\n $affix.$debouncedOnResize = debounce($affix.$onResize, 50);\n\n $affix.$parseOffsets = function() {\n var initialPosition = element.css('position');\n // Reset position to calculate correct offsetTop\n if (options.inlineStyles){\n element.css('position', (options.offsetParent) ? '' : 'relative');\n }\n\n if(options.offsetTop) {\n if(options.offsetTop === 'auto') {\n options.offsetTop = '+0';\n }\n if(options.offsetTop.match(/^[-+]\\d+$/)) {\n initialAffixTop = - options.offsetTop * 1;\n if(options.offsetParent) {\n offsetTop = dimensions.offset(parent[0]).top + (options.offsetTop * 1);\n }\n else {\n offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\n }\n }\n else {\n offsetTop = options.offsetTop * 1;\n }\n }\n\n if(options.offsetBottom) {\n if(options.offsetParent && options.offsetBottom.match(/^[-+]\\d+$/)) {\n // add 1 pixel due to rounding problems...\n offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + (options.offsetBottom * 1) + 1;\n }\n else {\n offsetBottom = options.offsetBottom * 1;\n }\n }\n\n // Bring back the element's position after calculations\n if (options.inlineStyles){\n element.css('position', initialPosition);\n }\n };\n\n // Private methods\n\n function getRequiredAffixClass(unpin, position, elementHeight) {\n\n var scrollTop = getScrollTop();\n var scrollHeight = getScrollHeight();\n\n if(scrollTop <= offsetTop) {\n return 'top';\n } else if(unpin !== null && (scrollTop + unpin <= position.top)) {\n return 'middle';\n } else if(offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n return 'bottom';\n } else {\n return 'middle';\n }\n\n }\n\n function getScrollTop() {\n return targetEl[0] === $window ? $window.pageYOffset : targetEl[0].scrollTop;\n }\n\n function getScrollHeight() {\n return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight;\n }\n\n $affix.init();\n return $affix;\n\n }\n\n return AffixFactory;\n\n };\n\n })\n\n .directive('bsAffix', function($affix, $window) {\n\n return {\n restrict: 'EAC',\n require: '^?bsAffixTarget',\n link: function postLink(scope, element, attr, affixTarget) {\n\n var options = {scope: scope, target: affixTarget ? affixTarget.$element : angular.element($window)};\n angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin', 'inlineStyles'], function(key) {\n if(angular.isDefined(attr[key])) {\n var option = attr[key];\n if (/true/i.test(option)) option = true;\n if (/false/i.test(option)) option = false;\n options[key] = option;\n }\n });\n\n var affix = $affix(element, options);\n scope.$on('$destroy', function() {\n affix && affix.destroy();\n options = null;\n affix = null;\n });\n\n }\n };\n\n })\n\n .directive('bsAffixTarget', function() {\n return {\n controller: function($element) {\n this.$element = $element;\n }\n };\n });\n\n// Source: button/button.js\nangular.module('mgcrea.ngStrap.button', [])\n\n .provider('$button', function() {\n\n var defaults = this.defaults = {\n activeClass:'active',\n toggleEvent:'click'\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsCheckboxGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"checkbox\"]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.attr('bs-checkbox', '');\n childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));\n });\n }\n\n };\n\n })\n\n .directive('bsCheckbox', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support label > input[type=\"checkbox\"]\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;\n if(constantValueRegExp.test(attr.trueValue)) {\n trueValue = scope.$eval(attr.trueValue);\n }\n var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;\n if(constantValueRegExp.test(attr.falseValue)) {\n falseValue = scope.$eval(attr.falseValue);\n }\n\n // Parse exotic values\n var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';\n if(hasExoticValues) {\n controller.$parsers.push(function(viewValue) {\n // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue);\n return viewValue ? trueValue : falseValue;\n });\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n return angular.equals(modelValue, trueValue);\n });\n // Fix rendering for exotic values\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n controller.$render();\n });\n }\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, trueValue);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n if(!isInput) {\n controller.$setViewValue(!activeElement.hasClass('active'));\n }\n if(!hasExoticValues) {\n controller.$render();\n }\n });\n });\n\n }\n\n };\n\n })\n\n .directive('bsRadioGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"radio\"]');\n angular.forEach(children, function(child) {\n angular.element(child).attr('bs-radio', '');\n angular.element(child).attr('ng-model', attr.ngModel);\n });\n }\n\n };\n\n })\n\n .directive('bsRadio', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support `label > input[type=\"radio\"]` markup\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var value;\n attr.$observe('value', function(v) {\n value = constantValueRegExp.test(v) ? scope.$eval(v) : v;\n controller.$render();\n });\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, value);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n controller.$setViewValue(value);\n controller.$render();\n });\n });\n\n }\n\n };\n\n });\n\n// Source: alert/alert.js\n// @BUG: following snippet won't compile correctly\n// @TODO: submit issue to core\n// ' ' +\n\nangular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal'])\n\n .provider('$alert', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'alert',\n prefixEvent: 'alert',\n placement: null,\n template: 'alert/alert.tpl.html',\n container: false,\n element: null,\n backdrop: false,\n keyboard: true,\n show: true,\n // Specific options\n duration: false,\n type: false,\n dismissable: true\n };\n\n this.$get = function($modal, $timeout) {\n\n function AlertFactory(config) {\n\n var $alert = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $alert = $modal(options);\n\n // Support scope as string options [/*title, content, */ type, dismissable]\n $alert.$scope.dismissable = !!options.dismissable;\n if(options.type) {\n $alert.$scope.type = options.type;\n }\n\n // Support auto-close duration\n var show = $alert.show;\n if(options.duration) {\n $alert.show = function() {\n show();\n $timeout(function() {\n $alert.hide();\n }, options.duration * 1000);\n };\n }\n\n return $alert;\n\n }\n\n return AlertFactory;\n\n };\n\n })\n\n .directive('bsAlert', function($window, $sce, $alert) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'placement', 'keyboard', 'html', 'container', 'animation', 'duration', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['keyboard', 'html', 'container', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content', 'type'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAlert && scope.$watch(attr.bsAlert, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize alert\n var alert = $alert(options);\n\n // Trigger\n element.on(attr.trigger || 'click', alert.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (alert) alert.destroy();\n options = null;\n alert = null;\n });\n\n }\n };\n\n });\n\n// Source: aside/aside.js\nangular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal'])\n\n .provider('$aside', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade-and-slide-right',\n prefixClass: 'aside',\n prefixEvent: 'aside',\n placement: 'right',\n template: 'aside/aside.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($modal) {\n\n function AsideFactory(config) {\n\n var $aside = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $aside = $modal(options);\n\n return $aside;\n\n }\n\n return AsideFactory;\n\n };\n\n })\n\n .directive('bsAside', function($window, $sce, $aside) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAside && scope.$watch(attr.bsAside, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize aside\n var aside = $aside(options);\n\n // Trigger\n element.on(attr.trigger || 'click', aside.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (aside) aside.destroy();\n options = null;\n aside = null;\n });\n\n }\n };\n\n });\n\n// Source: collapse/collapse.js\nangular.module('mgcrea.ngStrap.collapse', [])\n\n .provider('$collapse', function() {\n\n var defaults = this.defaults = {\n animation: 'am-collapse',\n disallowToggle: false,\n activeClass: 'in',\n startCollapsed: false,\n allowMultiple: false\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['disallowToggle', 'startCollapsed', 'allowMultiple'], function(key) {\n if(angular.isDefined($attrs[key]) && falseValueRegExp.test($attrs[key]))\n self.$options[key] = false;\n });\n\n self.$toggles = [];\n self.$targets = [];\n\n self.$viewChangeListeners = [];\n\n self.$registerToggle = function(element) {\n self.$toggles.push(element);\n };\n self.$registerTarget = function(element) {\n self.$targets.push(element);\n };\n\n self.$unregisterToggle = function(element) {\n var index = self.$toggles.indexOf(element);\n // remove toggle from $toggles array\n self.$toggles.splice(index, 1);\n };\n self.$unregisterTarget = function(element) {\n var index = self.$targets.indexOf(element);\n\n // remove element from $targets array\n self.$targets.splice(index, 1);\n\n if (self.$options.allowMultiple) {\n // remove target index from $active array values\n deactivateItem(element);\n }\n\n // fix active item indexes\n fixActiveItemIndexes(index);\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n // use array to store all the currently open panels\n self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n self.$setActive = $scope.$setActive = function(value) {\n if(angular.isArray(value)) {\n self.$targets.$active = value;\n }\n else if(!self.$options.disallowToggle) {\n // toogle element active status\n isActive(value) ? deactivateItem(value) : activateItem(value);\n } else {\n activateItem(value);\n }\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$activeIndexes = function() {\n return self.$options.allowMultiple ? self.$targets.$active :\n self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n };\n\n function fixActiveItemIndexes(index) {\n // item with index was removed, so we\n // need to adjust other items index values\n var activeIndexes = self.$targets.$active;\n for(var i = 0; i < activeIndexes.length; i++) {\n if (index < activeIndexes[i]) {\n activeIndexes[i] = activeIndexes[i] - 1;\n }\n\n // the last item is active, so we need to\n // adjust its index\n if (activeIndexes[i] === self.$targets.length) {\n activeIndexes[i] = self.$targets.length - 1;\n }\n }\n }\n\n function isActive(value) {\n var activeItems = self.$targets.$active;\n return activeItems.indexOf(value) === -1 ? false : true;\n }\n\n function deactivateItem(value) {\n var index = self.$targets.$active.indexOf(value);\n if (index !== -1) {\n self.$targets.$active.splice(index, 1);\n }\n }\n\n function activateItem(value) {\n if (!self.$options.allowMultiple) {\n // remove current selected item\n self.$targets.$active.splice(0, 1);\n }\n\n if (self.$targets.$active.indexOf(value) === -1) {\n self.$targets.$active.push(value);\n }\n }\n\n };\n\n this.$get = function() {\n var $collapse = {};\n $collapse.defaults = defaults;\n $collapse.controller = controller;\n return $collapse;\n };\n\n })\n\n .directive('bsCollapse', function($window, $animate, $collapse) {\n\n var defaults = $collapse.defaults;\n\n return {\n require: ['?ngModel', 'bsCollapse'],\n controller: ['$scope', '$element', '$attrs', $collapse.controller],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n if (angular.isArray(modelValue)) {\n // model value is an array, so just replace\n // the active items directly\n bsCollapseCtrl.$setActive(modelValue);\n }\n else {\n var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n if (angular.isArray(activeIndexes)) {\n // we have an array of selected indexes\n if (activeIndexes.indexOf(modelValue * 1) === -1) {\n // item with modelValue index is not active\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n else if (activeIndexes !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n return modelValue;\n });\n\n }\n\n }\n };\n\n })\n\n .directive('bsCollapseToggle', function() {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base attr\n element.attr('data-toggle', 'collapse');\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerToggle(element);\n\n // remove toggle from collapse controller when toggle is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterToggle(element);\n });\n\n element.on('click', function() {\n var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n bsCollapseCtrl.$setActive(index * 1);\n scope.$apply();\n });\n\n }\n };\n\n })\n\n .directive('bsCollapseTarget', function($animate) {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n // scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base class\n element.addClass('collapse');\n\n // Add animation class\n if(bsCollapseCtrl.$options.animation) {\n element.addClass(bsCollapseCtrl.$options.animation);\n }\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerTarget(element);\n\n // remove pane target from collapse controller when target is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterTarget(element);\n });\n\n function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$activeIndexes();\n var action = 'removeClass';\n if (angular.isArray(active)) {\n if (active.indexOf(index) !== -1) {\n action = 'addClass';\n }\n }\n else if (index === active) {\n action = 'addClass';\n }\n\n $animate[action](element, bsCollapseCtrl.$options.activeClass);\n }\n\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n\n// Source: datepicker/datepicker.js\nangular.module('mgcrea.ngStrap.datepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$datepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'datepicker',\n prefixClass: 'datepicker',\n placement: 'bottom-left',\n template: 'datepicker/datepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: false,\n dateType: 'date',\n dateFormat: 'shortDate',\n timezone: null,\n modelDateFormat: null,\n dayFormat: 'dd',\n monthFormat: 'MMM',\n yearFormat: 'yyyy',\n monthTitleFormat: 'MMMM yyyy',\n yearTitleFormat: 'yyyy',\n strictFormat: false,\n autoclose: false,\n minDate: -Infinity,\n maxDate: +Infinity,\n startView: 0,\n minView: 0,\n startWeek: 0,\n daysOfWeekDisabled: '',\n iconLeft: 'glyphicon glyphicon-chevron-left',\n iconRight: 'glyphicon glyphicon-chevron-right'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function DatepickerFactory(element, controller, config) {\n\n var $datepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $datepicker.$options;\n var scope = $datepicker.$scope;\n if(options.startView) options.startView -= options.minView;\n\n // View vars\n\n var pickerViews = datepickerViews($datepicker);\n $datepicker.$views = pickerViews.views;\n var viewDate = pickerViews.viewDate;\n scope.$mode = options.startView;\n scope.$iconLeft = options.iconLeft;\n scope.$iconRight = options.iconRight;\n var $picker = $datepicker.$views[scope.$mode];\n\n // Scope methods\n\n scope.$select = function(date) {\n $datepicker.select(date);\n };\n scope.$selectPane = function(value) {\n $datepicker.$selectPane(value);\n };\n scope.$toggleMode = function() {\n $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);\n };\n\n // Public methods\n\n $datepicker.update = function(date) {\n // console.warn('$datepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $datepicker.$date = date;\n $picker.update.call($picker, date);\n }\n // Build only if pristine\n $datepicker.$build(true);\n };\n\n $datepicker.updateDisabledDates = function(dateRanges) {\n options.disabledDateRanges = dateRanges;\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);\n }\n };\n\n $datepicker.select = function(date, keep) {\n // console.warn('$datepicker.select', date, scope.$mode);\n if(!angular.isDate(controller.$dateValue)) controller.$dateValue = new Date(date);\n if(!scope.$mode || keep) {\n controller.$setViewValue(angular.copy(date));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $datepicker.hide(true); });\n }\n } else {\n angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});\n $datepicker.setMode(scope.$mode - 1);\n $datepicker.$build();\n }\n };\n\n $datepicker.setMode = function(mode) {\n // console.warn('$datepicker.setMode', mode);\n scope.$mode = mode;\n $picker = $datepicker.$views[scope.$mode];\n $datepicker.$build();\n };\n\n // Protected methods\n\n $datepicker.$build = function(pristine) {\n // console.warn('$datepicker.$build() viewDate=%o', viewDate);\n if(pristine === true && $picker.built) return;\n if(pristine === false && !$picker.built) return;\n $picker.build.call($picker);\n };\n\n $datepicker.$updateSelected = function() {\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], updateSelected);\n }\n };\n\n $datepicker.$isSelected = function(date) {\n return $picker.isSelected(date);\n };\n\n $datepicker.$setDisabledEl = function(el) {\n el.disabled = $picker.isDisabled(el.date);\n };\n\n $datepicker.$selectPane = function(value) {\n var steps = $picker.steps;\n // set targetDate to first day of month to avoid problems with\n // date values rollover. This assumes the viewDate does not\n // depend on the day of the month\n var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));\n angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});\n $datepicker.$build();\n };\n\n $datepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $datepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n if(evt.keyCode === 13) {\n if(!scope.$mode) {\n return $datepicker.hide(true);\n } else {\n return scope.$apply(function() { $datepicker.setMode(scope.$mode - 1); });\n }\n }\n\n // Navigate with keyboard\n $picker.onKeyDown(evt);\n parentScope.$digest();\n };\n\n // Private\n\n function updateSelected(el) {\n el.selected = $datepicker.$isSelected(el.date);\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $datepicker.init;\n $datepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'date');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $datepicker.destroy;\n $datepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $datepicker.show;\n $datepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // if $datepicker is no longer showing, don't setup events\n if(!$datepicker.$isShown) return;\n $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $datepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $datepicker.hide;\n $datepicker.hide = function(blur) {\n if(!$datepicker.$isShown) return;\n $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $datepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $datepicker;\n\n }\n\n DatepickerFactory.defaults = defaults;\n return DatepickerFactory;\n\n };\n\n })\n\n .directive('bsDatepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {\n\n var defaults = $datepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'timezone', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!datepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);\n newValue === true ? datepicker.show() : datepicker.hide();\n });\n\n // Initialize datepicker\n var datepicker = $datepicker(element, controller, options);\n options = datepicker.$options;\n // Set expected iOS format\n if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';\n\n var lang = options.lang;\n\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n // Observe attributes for changes\n angular.forEach(['minDate', 'maxDate'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n // console.warn('attr.$observe(%s)=%o', key, newValue);\n datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);\n // Build only if dirty\n !isNaN(datepicker.$options[key]) && datepicker.$build(false);\n validateAgainstMinMaxDate(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n datepicker.update(controller.$dateValue);\n }, true);\n\n // Normalize undefined/null/empty array,\n // so that we don't treat changing from undefined->null as a change.\n function normalizeDateRanges(ranges) {\n if (!ranges || !ranges.length) return null;\n return ranges;\n }\n\n if (angular.isDefined(attr.disabledDates)) {\n scope.$watch(attr.disabledDates, function(disabledRanges, previousValue) {\n disabledRanges = normalizeDateRanges(disabledRanges);\n previousValue = normalizeDateRanges(previousValue);\n\n if (disabledRanges) {\n datepicker.updateDisabledDates(disabledRanges);\n }\n });\n }\n\n function validateAgainstMinMaxDate(parsedDate) {\n if (!angular.isDate(parsedDate)) return;\n var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;\n var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(isValid) controller.$dateValue = parsedDate;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n controller.$setValidity('date', true);\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n return null;\n }\n var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedDate || isNaN(parsedDate.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxDate(parsedDate);\n }\n\n if(options.dateType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedDate, options.timezone, true);\n return formatDate(date, options.modelDateFormat || options.dateFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.dateType === 'number') {\n return date.getTime();\n } else if(options.dateType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.dateType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.dateType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelDateFormat);\n } else if(options.dateType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) {\n // var today = new Date();\n // date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n // }\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getDateFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getDateFormattedString());\n };\n\n function getDateFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(datepicker) datepicker.destroy();\n options = null;\n datepicker = null;\n });\n\n }\n };\n\n })\n\n .provider('datepickerViews', function() {\n\n var defaults = this.defaults = {\n dayFormat: 'dd',\n daySplit: 7\n };\n\n // Split array into smaller arrays\n function split(arr, size) {\n var arrays = [];\n while(arr.length > 0) {\n arrays.push(arr.splice(0, size));\n }\n return arrays;\n }\n\n // Modulus operator\n function mod(n, m) {\n return ((n % m) + m) % m;\n }\n\n this.$get = function($dateFormatter, $dateParser, $sce) {\n\n return function(picker) {\n\n var scope = picker.$scope;\n var options = picker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n var weekDaysLabelsHtml = $sce.trustAsHtml('' + weekDaysLabels.join('') + '');\n\n var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n\n var views = [{\n format: options.dayFormat,\n split: 7,\n steps: { month: 1 },\n update: function(date, force) {\n if(!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getDate() !== viewDate.date || date.getDate() === 1) {\n // chaging picker current month will cause viewDate.date to be set to first day of the month,\n // in $datepicker.$selectPane, so picker would not update selected day display if\n // user picks first day of the new month.\n // As a workaround, we are always forcing update when picked date is first day of month.\n viewDate.date = picker.$date.getDate();\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5), firstDateOffset = firstDate.getTimezoneOffset();\n var today = dateParser.timezoneOffsetAdjust(new Date(), options.timezone).toDateString();\n // Handle daylight time switch\n if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);\n var days = [], day;\n for(var i = 0; i < 42; i++) { // < 7 * 6\n day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));\n days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n }\n scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);\n scope.showLabels = true;\n scope.labels = weekDaysLabelsHtml;\n scope.rows = split(days, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();\n },\n isDisabled: function(date) {\n var time = date.getTime();\n\n // Disabled because of min/max date.\n if (time < options.minDate || time > options.maxDate) return true;\n\n // Disabled due to being a disabled day of the week\n if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;\n\n // Disabled because of disabled date range.\n if (options.disabledDateRanges) {\n for (var i = 0; i < options.disabledDateRanges.length; i++) {\n if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {\n return true;\n }\n }\n }\n\n return false;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualTime = picker.$date.getTime();\n var newDate;\n\n if(evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);\n else if(evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);\n else if(evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);\n else if(evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'month',\n format: options.monthFormat,\n split: 4,\n steps: { year: 1 },\n update: function(date, force) {\n if(!this.built || date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstMonth = new Date(viewDate.year, 0, 1);\n var months = [], month;\n for (var i = 0; i < 12; i++) {\n month = new Date(viewDate.year, i, 1);\n months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n }\n scope.title = formatDate(month, options.yearTitleFormat);\n scope.showLabels = false;\n scope.rows = split(months, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualMonth = picker.$date.getMonth();\n var newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setMonth(actualMonth - 1);\n else if(evt.keyCode === 38) newDate.setMonth(actualMonth - 4);\n else if(evt.keyCode === 39) newDate.setMonth(actualMonth + 1);\n else if(evt.keyCode === 40) newDate.setMonth(actualMonth + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'year',\n format: options.yearFormat,\n split: 4,\n steps: { year: 12 },\n update: function(date, force) {\n if(!this.built || force || parseInt(date.getFullYear()/20, 10) !== parseInt(viewDate.year/20, 10)) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstYear = viewDate.year - viewDate.year % (this.split * 3);\n var years = [], year;\n for (var i = 0; i < 12; i++) {\n year = new Date(firstYear + i, 0, 1);\n years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});\n }\n scope.title = years[0].label + '-' + years[years.length - 1].label;\n scope.showLabels = false;\n scope.rows = split(years, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear() + 1, 0, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualYear = picker.$date.getFullYear(),\n newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setYear(actualYear - 1);\n else if(evt.keyCode === 38) newDate.setYear(actualYear - 4);\n else if(evt.keyCode === 39) newDate.setYear(actualYear + 1);\n else if(evt.keyCode === 40) newDate.setYear(actualYear + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }];\n\n return {\n views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,\n viewDate: viewDate\n };\n\n };\n\n };\n\n });\n\n// Source: dropdown/dropdown.js\nangular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$dropdown', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'dropdown',\n prefixEvent: 'dropdown',\n placement: 'bottom-left',\n template: 'dropdown/dropdown.tpl.html',\n trigger: 'click',\n container: false,\n keyboard: true,\n html: false,\n delay: 0\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;\n\n function DropdownFactory(element, config) {\n\n var $dropdown = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n $dropdown = $tooltip(element, options);\n var parentEl = element.parent();\n\n // Protected methods\n\n $dropdown.$onKeyDown = function(evt) {\n if (!/(38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Retrieve focused index\n var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));\n if(!items.length) return;\n var index;\n angular.forEach(items, function(el, i) {\n if(matchesSelector && matchesSelector.call(el, ':focus')) index = i;\n });\n\n // Navigate with keyboard\n if(evt.keyCode === 38 && index > 0) index--;\n else if(evt.keyCode === 40 && index < items.length - 1) index++;\n else if(angular.isUndefined(index)) index = 0;\n items.eq(index)[0].focus();\n\n };\n\n // Overrides\n\n var show = $dropdown.show;\n $dropdown.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n bodyEl.on('click', onBodyClick);\n }, 0, false);\n parentEl.hasClass('dropdown') && parentEl.addClass('open');\n };\n\n var hide = $dropdown.hide;\n $dropdown.hide = function() {\n if(!$dropdown.$isShown) return;\n options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n bodyEl.off('click', onBodyClick);\n parentEl.hasClass('dropdown') && parentEl.removeClass('open');\n hide();\n };\n\n var destroy = $dropdown.destroy;\n $dropdown.destroy = function() {\n bodyEl.off('click', onBodyClick);\n destroy();\n };\n\n // Private functions\n\n function onBodyClick(evt) {\n if(evt.target === element[0]) return;\n return evt.target !== element[0] && $dropdown.hide();\n }\n\n return $dropdown;\n\n }\n\n return DropdownFactory;\n\n };\n\n })\n\n .directive('bsDropdown', function($window, $sce, $dropdown) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as an object\n attr.bsDropdown && scope.$watch(attr.bsDropdown, function(newValue, oldValue) {\n scope.content = newValue;\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!dropdown || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(dropdown),?/i);\n newValue === true ? dropdown.show() : dropdown.hide();\n });\n\n // Initialize dropdown\n var dropdown = $dropdown(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (dropdown) dropdown.destroy();\n options = null;\n dropdown = null;\n });\n\n }\n };\n\n });\n\n// Source: helpers/date-formatter.js\nangular.module('mgcrea.ngStrap.helpers.dateFormatter', [])\n\n .service('$dateFormatter', function($locale, dateFilter) {\n\n // The unused `lang` arguments are on purpose. The default implementation does not\n // use them and it always uses the locale loaded into the `$locale` service.\n // Custom implementations might use it, thus allowing different directives to\n // have different languages.\n\n this.getDefaultLocale = function() {\n return $locale.id;\n };\n\n // Format is either a data format name, e.g. \"shortTime\" or \"fullDate\", or a date format\n // Return either the corresponding date format or the given date format.\n this.getDatetimeFormat = function(format, lang) {\n return $locale.DATETIME_FORMATS[format] || format;\n };\n\n this.weekdaysShort = function(lang) {\n return $locale.DATETIME_FORMATS.SHORTDAY;\n };\n\n function splitTimeFormat(format) {\n return /(h+)([:\\.])?(m+)([:\\.])?(s*)[ ]?(a?)/i.exec(format).slice(1);\n }\n\n // h:mm a => h\n this.hoursFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[0];\n };\n\n // h:mm a => mm\n this.minutesFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[2];\n };\n\n // h:mm:ss a => ss\n this.secondsFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => :\n this.timeSeparator = function(timeFormat) {\n return splitTimeFormat(timeFormat)[1];\n };\n\n // h:mm:ss a => true, h:mm a => false\n this.showSeconds = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => true, H.mm => false\n this.showAM = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[5];\n };\n\n this.formatDate = function(date, format, lang, timezone){\n return dateFilter(date, format, timezone);\n };\n\n });\n\n// Source: helpers/date-parser.js\nangular.module('mgcrea.ngStrap.helpers.dateParser', [])\n\n.provider('$dateParser', function($localeProvider) {\n\n // define a custom ParseDate object to use instead of native Date\n // to avoid date values wrapping when setting date component values\n function ParseDate() {\n this.year = 1970;\n this.month = 0;\n this.day = 1;\n this.hours = 0;\n this.minutes = 0;\n this.seconds = 0;\n this.milliseconds = 0;\n }\n\n ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };\n ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };\n ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };\n ParseDate.prototype.setHours = function(value) { this.hours = value; };\n ParseDate.prototype.getHours = function() { return this.hours; };\n ParseDate.prototype.setDate = function(value) { this.day = value; };\n ParseDate.prototype.setMonth = function(value) { this.month = value; };\n ParseDate.prototype.setFullYear = function(value) { this.year = value; };\n ParseDate.prototype.fromDate = function(value) {\n this.year = value.getFullYear();\n this.month = value.getMonth();\n this.day = value.getDate();\n this.hours = value.getHours();\n this.minutes = value.getMinutes();\n this.seconds = value.getSeconds();\n this.milliseconds = value.getMilliseconds();\n return this;\n };\n\n ParseDate.prototype.toDate = function() {\n return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n };\n\n var proto = ParseDate.prototype;\n\n function noop() {\n }\n\n function isNumeric(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n function indexOfCaseInsensitive(array, value) {\n var len = array.length, str=value.toString().toLowerCase();\n for (var i=0; i 12 when midnight changeover, but then cannot generate\n * midnight datetime, so jump to 1AM, otherwise reset.\n * @param date (Date) the date to check\n * @return (Date) the corrected date\n *\n * __ copied from jquery ui datepicker __\n */\n $dateParser.daylightSavingAdjust = function(date) {\n if (!date) {\n return null;\n }\n date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n return date;\n };\n\n /* Correct the date for timezone offset.\n * @param date (Date) the date to adjust\n * @param timezone (string) the timezone to adjust for\n * @param undo (boolean) to add or subtract timezone offset\n * @return (Date) the corrected date\n */\n $dateParser.timezoneOffsetAdjust = function(date, timezone, undo) {\n if (!date) {\n return null;\n }\n // Right now, only 'UTC' is supported.\n if (timezone && timezone === 'UTC') {\n date = new Date(date.getTime());\n date.setMinutes(date.getMinutes() + (undo?-1:1)*date.getTimezoneOffset());\n }\n return date;\n };\n\n // Private functions\n\n function setMapForFormat(format) {\n var keys = Object.keys(setFnMap), i;\n var map = [], sortedMap = [];\n // Map to setFn\n var clonedFormat = format;\n for(i = 0; i < keys.length; i++) {\n if(format.split(keys[i]).length > 1) {\n var index = clonedFormat.search(keys[i]);\n format = format.split(keys[i]).join('');\n if(setFnMap[keys[i]]) {\n map[index] = setFnMap[keys[i]];\n }\n }\n }\n // Sort result map\n angular.forEach(map, function(v) {\n // conditional required since angular.forEach broke around v1.2.21\n // related pr: https://github.com/angular/angular.js/pull/8525\n if(v) sortedMap.push(v);\n });\n return sortedMap;\n }\n\n function escapeReservedSymbols(text) {\n return text.replace(/\\//g, '[\\\\/]').replace('/-/g', '[-]').replace(/\\./g, '[.]').replace(/\\\\s/g, '[\\\\s]');\n }\n\n function regExpForFormat(format) {\n var keys = Object.keys(regExpMap), i;\n\n var re = format;\n // Abstract replaces to avoid collisions\n for(i = 0; i < keys.length; i++) {\n re = re.split(keys[i]).join('${' + i + '}');\n }\n // Replace abstracted values\n for(i = 0; i < keys.length; i++) {\n re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');\n }\n format = escapeReservedSymbols(format);\n\n return new RegExp('^' + re + '$', ['i']);\n }\n\n $dateParser.init();\n return $dateParser;\n\n };\n\n return DateParserFactory;\n\n };\n\n});\n\n// Source: helpers/debounce.js\nangular.module('mgcrea.ngStrap.helpers.debounce', [])\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L693\n.factory('debounce', function($timeout) {\n return function(func, wait, immediate) {\n var timeout = null;\n return function() {\n var context = this,\n args = arguments,\n callNow = immediate && !timeout;\n if(timeout) {\n $timeout.cancel(timeout);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(!immediate) {\n func.apply(context, args);\n }\n }, wait, false);\n if(callNow) {\n func.apply(context, args);\n }\n return timeout;\n };\n };\n})\n\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L661\n.factory('throttle', function($timeout) {\n return function(func, wait, options) {\n var timeout = null;\n options || (options = {});\n return function() {\n var context = this,\n args = arguments;\n if(!timeout) {\n if(options.leading !== false) {\n func.apply(context, args);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(options.trailing !== false) {\n func.apply(context, args);\n }\n }, wait, false);\n }\n };\n };\n});\n\n// Source: helpers/dimensions.js\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n .factory('dimensions', function($document, $window) {\n\n var jqLite = angular.element;\n var fn = {};\n\n /**\n * Test the element nodeName\n * @param element\n * @param name\n */\n var nodeName = fn.nodeName = function(element, name) {\n return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();\n };\n\n /**\n * Returns the element computed style\n * @param element\n * @param prop\n * @param extra\n */\n fn.css = function(element, prop, extra) {\n var value;\n if (element.currentStyle) { //IE\n value = element.currentStyle[prop];\n } else if (window.getComputedStyle) {\n value = window.getComputedStyle(element)[prop];\n } else {\n value = element.style[prop];\n }\n return extra === true ? parseFloat(value) || 0 : value;\n };\n\n /**\n * Provides read-only equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.offset = function(element) {\n var boxRect = element.getBoundingClientRect();\n var docElement = element.ownerDocument;\n return {\n width: boxRect.width || element.offsetWidth,\n height: boxRect.height || element.offsetHeight,\n top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),\n left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)\n };\n };\n \n /**\n * Provides set equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip\n * @url http://api.jquery.com/offset/\n * @param element\n * @param options\n * @param i\n */\n fn.setOffset = function (element, options, i) {\n var curPosition,\n curLeft,\n curCSSTop,\n curTop,\n curOffset,\n curCSSLeft,\n calculatePosition,\n position = fn.css(element, 'position'),\n curElem = angular.element(element),\n props = {};\n \n // Set position first, in-case top/left are set even on static elem\n if (position === 'static') {\n element.style.position = 'relative';\n }\n \n curOffset = fn.offset(element);\n curCSSTop = fn.css(element, 'top');\n curCSSLeft = fn.css(element, 'left');\n calculatePosition = (position === 'absolute' || position === 'fixed') && \n (curCSSTop + curCSSLeft).indexOf('auto') > -1;\n \n // Need to be able to calculate position if either\n // top or left is auto and position is either absolute or fixed\n if (calculatePosition) {\n curPosition = fn.position(element);\n curTop = curPosition.top;\n curLeft = curPosition.left;\n } else {\n curTop = parseFloat(curCSSTop) || 0;\n curLeft = parseFloat(curCSSLeft) || 0;\n }\n \n if (angular.isFunction(options)) {\n options = options.call(element, i, curOffset);\n }\n \n if (options.top !== null ) {\n props.top = (options.top - curOffset.top) + curTop;\n }\n if ( options.left !== null ) {\n props.left = (options.left - curOffset.left) + curLeft;\n }\n\n if ('using' in options) {\n options.using.call(curElem, props);\n } else {\n curElem.css({\n top: props.top + 'px',\n left: props.left + 'px'\n });\n }\n };\n\n /**\n * Provides read-only equivalent of jQuery's position function\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.position = function(element) {\n\n var offsetParentRect = {top: 0, left: 0},\n offsetParentElement,\n offset;\n\n // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n if (fn.css(element, 'position') === 'fixed') {\n\n // We assume that getBoundingClientRect is available when computed position is fixed\n offset = element.getBoundingClientRect();\n\n } else {\n\n // Get *real* offsetParentElement\n offsetParentElement = offsetParent(element);\n\n // Get correct offsets\n offset = fn.offset(element);\n if (!nodeName(offsetParentElement, 'html')) {\n offsetParentRect = fn.offset(offsetParentElement);\n }\n\n // Add offsetParent borders\n offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);\n offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);\n }\n\n // Subtract parent offsets and element margins\n return {\n width: element.offsetWidth,\n height: element.offsetHeight,\n top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),\n left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)\n };\n\n };\n\n /**\n * Returns the closest, non-statically positioned offsetParent of a given element\n * @required-by fn.position\n * @param element\n */\n var offsetParent = function offsetParentElement(element) {\n var docElement = element.ownerDocument;\n var offsetParent = element.offsetParent || docElement;\n if(nodeName(offsetParent, '#document')) return docElement.documentElement;\n while(offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {\n offsetParent = offsetParent.offsetParent;\n }\n return offsetParent || docElement.documentElement;\n };\n\n /**\n * Provides equivalent of jQuery's height function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/height/\n * @param element\n * @param outer\n */\n fn.height = function(element, outer) {\n var value = element.offsetHeight;\n if(outer) {\n value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);\n } else {\n value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);\n }\n return value;\n };\n\n /**\n * Provides equivalent of jQuery's width function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/width/\n * @param element\n * @param outer\n */\n fn.width = function(element, outer) {\n var value = element.offsetWidth;\n if(outer) {\n value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);\n } else {\n value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);\n }\n return value;\n };\n\n return fn;\n\n });\n\n// Source: helpers/parse-options.js\nangular.module('mgcrea.ngStrap.helpers.parseOptions', [])\n\n .provider('$parseOptions', function() {\n\n var defaults = this.defaults = {\n regexp: /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w]*)|(?:\\(\\s*([\\$\\w][\\$\\w]*)\\s*,\\s*([\\$\\w][\\$\\w]*)\\s*\\)))\\s+in\\s+(.*?)(?:\\s+track\\s+by\\s+(.*?))?$/\n };\n\n this.$get = function($parse, $q) {\n\n function ParseOptionsFactory(attr, config) {\n\n var $parseOptions = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n $parseOptions.$values = [];\n\n // Private vars\n var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;\n\n $parseOptions.init = function() {\n $parseOptions.$match = match = attr.match(options.regexp);\n displayFn = $parse(match[2] || match[1]),\n valueName = match[4] || match[6],\n keyName = match[5],\n groupByFn = $parse(match[3] || ''),\n valueFn = $parse(match[2] ? match[1] : valueName),\n valuesFn = $parse(match[7]);\n };\n\n $parseOptions.valuesFn = function(scope, controller) {\n return $q.when(valuesFn(scope, controller))\n .then(function(values) {\n $parseOptions.$values = values ? parseValues(values, scope) : {};\n return $parseOptions.$values;\n });\n };\n\n $parseOptions.displayValue = function(modelValue) {\n var scope = {};\n scope[valueName] = modelValue;\n return displayFn(scope);\n };\n\n // Private functions\n\n function parseValues(values, scope) {\n return values.map(function(match, index) {\n var locals = {}, label, value;\n locals[valueName] = match;\n label = displayFn(scope, locals);\n value = valueFn(scope, locals);\n return {label: label, value: value, index: index};\n });\n }\n\n $parseOptions.init();\n return $parseOptions;\n\n }\n\n return ParseOptionsFactory;\n\n };\n\n });\n\n// Source: helpers/raf.js\n(angular.version.minor < 3 && angular.version.dot < 14) && angular.module('ng')\n\n.factory('$$rAF', function($window, $timeout) {\n\n var requestAnimationFrame = $window.requestAnimationFrame ||\n $window.webkitRequestAnimationFrame ||\n $window.mozRequestAnimationFrame;\n\n var cancelAnimationFrame = $window.cancelAnimationFrame ||\n $window.webkitCancelAnimationFrame ||\n $window.mozCancelAnimationFrame ||\n $window.webkitCancelRequestAnimationFrame;\n\n var rafSupported = !!requestAnimationFrame;\n var raf = rafSupported ?\n function(fn) {\n var id = requestAnimationFrame(fn);\n return function() {\n cancelAnimationFrame(id);\n };\n } :\n function(fn) {\n var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n return function() {\n $timeout.cancel(timer);\n };\n };\n\n raf.supported = rafSupported;\n\n return raf;\n\n});\n\n// .factory('$$animateReflow', function($$rAF, $document) {\n\n// var bodyEl = $document[0].body;\n\n// return function(fn) {\n// //the returned function acts as the cancellation function\n// return $$rAF(function() {\n// //the line below will force the browser to perform a repaint\n// //so that all the animated elements within the animation frame\n// //will be properly updated and drawn on screen. This is\n// //required to perform multi-class CSS based animations with\n// //Firefox. DO NOT REMOVE THIS LINE.\n// var a = bodyEl.offsetWidth + 1;\n// fn();\n// });\n// };\n\n// });\n\n// Source: modal/modal.js\nangular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$modal', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n backdropAnimation: 'am-fade',\n prefixClass: 'modal',\n prefixEvent: 'modal',\n placement: 'top',\n template: 'modal/modal.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {\n\n var forEach = angular.forEach;\n var trim = String.prototype.trim;\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n var bodyElement = angular.element($window.document.body);\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n\n function ModalFactory(config) {\n\n var $modal = {};\n\n // Common vars\n var options = $modal.$options = angular.extend({}, defaults, config);\n $modal.$promise = fetchTemplate(options.template);\n var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(!options.element && !options.container) {\n options.container = 'body';\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $modal.$id = options.id || options.element && options.element.attr('id') || '';\n\n // Support scope as string options\n forEach(['title', 'content'], function(key) {\n if(options[key]) scope[key] = $sce.trustAsHtml(options[key]);\n });\n\n // Provide scope helpers\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $modal.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $modal.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $modal.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $modal.$isShown = scope.$isShown = false;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $modal.$promise = $modal.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);\n // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n if(!config.template) contentEl.next().remove();\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize modal\n var modalLinker, modalElement;\n var backdropElement = angular.element('
');\n backdropElement.css({position:'fixed', top:'0px', left:'0px', bottom:'0px', right:'0px', 'z-index': 1038});\n $modal.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n modalLinker = $compile(template);\n $modal.init();\n });\n\n $modal.init = function() {\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n $modal.show();\n });\n }\n\n };\n\n $modal.destroy = function() {\n\n // Remove element\n if(modalElement) {\n modalElement.remove();\n modalElement = null;\n }\n if(backdropElement) {\n backdropElement.remove();\n backdropElement = null;\n }\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $modal.show = function() {\n if($modal.$isShown) return;\n\n var parent, after;\n if(angular.isElement(options.container)) {\n parent = options.container;\n after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;\n } else {\n if (options.container) {\n parent = findElement(options.container);\n after = parent[0] && parent[0].lastChild ? angular.element(parent[0].lastChild) : null;\n } else {\n parent = null;\n after = options.element;\n }\n }\n\n // Fetch a cloned element linked from template\n modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\n\n if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n return;\n }\n\n // Set the initial positioning.\n modalElement.css({display: 'block'}).addClass(options.placement);\n\n // Options: animation\n if(options.animation) {\n if(options.backdrop) {\n backdropElement.addClass(options.backdropAnimation);\n }\n modalElement.addClass(options.animation);\n }\n\n if(options.backdrop) {\n $animate.enter(backdropElement, bodyElement, null);\n }\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.enter(modalElement, parent, after, enterAnimateCallback);\n if(promise && promise.then) promise.then(enterAnimateCallback);\n\n $modal.$isShown = scope.$isShown = true;\n safeDigest(scope);\n // Focus once the enter-animation has started\n // Weird PhantomJS bug hack\n var el = modalElement[0];\n requestAnimationFrame(function() {\n el.focus();\n });\n\n bodyElement.addClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n }\n\n // Bind events\n if(options.backdrop) {\n modalElement.on('click', hideOnBackdropClick);\n backdropElement.on('click', hideOnBackdropClick);\n backdropElement.on('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.on('keyup', $modal.$onKeyUp);\n }\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $modal);\n }\n\n $modal.hide = function() {\n if(!$modal.$isShown) return;\n\n if(scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {\n return;\n }\n var promise = $animate.leave(modalElement, leaveAnimateCallback);\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n if(options.backdrop) {\n $animate.leave(backdropElement);\n }\n $modal.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.backdrop) {\n modalElement.off('click', hideOnBackdropClick);\n backdropElement.off('click', hideOnBackdropClick);\n backdropElement.off('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.off('keyup', $modal.$onKeyUp);\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $modal);\n bodyElement.removeClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n }\n }\n\n $modal.toggle = function() {\n\n $modal.$isShown ? $modal.hide() : $modal.show();\n\n };\n\n $modal.focus = function() {\n modalElement[0].focus();\n };\n\n // Protected methods\n\n $modal.$onKeyUp = function(evt) {\n\n if (evt.which === 27 && $modal.$isShown) {\n $modal.hide();\n evt.stopPropagation();\n }\n\n };\n\n // Private methods\n\n function hideOnBackdropClick(evt) {\n if(evt.target !== evt.currentTarget) return;\n options.backdrop === 'static' ? $modal.focus() : $modal.hide();\n }\n\n function preventEventDefault(evt) {\n evt.preventDefault();\n }\n\n return $modal;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return ModalFactory;\n\n };\n\n })\n\n .directive('bsModal', function($window, $sce, $modal) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsModal && scope.$watch(attr.bsModal, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize modal\n var modal = $modal(options);\n\n // Trigger\n element.on(attr.trigger || 'click', modal.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (modal) modal.destroy();\n options = null;\n modal = null;\n });\n\n }\n };\n\n });\n\n// Source: navbar/navbar.js\nangular.module('mgcrea.ngStrap.navbar', [])\n\n .provider('$navbar', function() {\n\n var defaults = this.defaults = {\n activeClass: 'active',\n routeAttr: 'data-match-route',\n strict: false\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsNavbar', function($window, $location, $navbar) {\n\n var defaults = $navbar.defaults;\n\n return {\n restrict: 'A',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = angular.copy(defaults);\n angular.forEach(Object.keys(defaults), function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Watch for the $location\n scope.$watch(function() {\n\n return $location.path();\n\n }, function(newValue, oldValue) {\n\n var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');\n\n angular.forEach(liElements, function(li) {\n\n var liElement = angular.element(li);\n var pattern = liElement.attr(options.routeAttr).replace('/', '\\\\/');\n if(options.strict) {\n pattern = '^' + pattern + '$';\n }\n var regexp = new RegExp(pattern, 'i');\n\n if(regexp.test(newValue)) {\n liElement.addClass(options.activeClass);\n } else {\n liElement.removeClass(options.activeClass);\n }\n\n });\n\n });\n\n }\n\n };\n\n });\n\n// Source: popover/popover.js\nangular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$popover', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n // uncommenting the next two lines will break backwards compatability\n // prefixClass: 'popover',\n // prefixEvent: 'popover',\n container: false,\n target: false,\n placement: 'right',\n template: 'popover/popover.tpl.html',\n contentTemplate: false,\n trigger: 'click',\n keyboard: true,\n html: false,\n title: '',\n content: '',\n delay: 0,\n autoClose: false\n };\n\n this.$get = function($tooltip) {\n\n function PopoverFactory(element, config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n var $popover = $tooltip(element, options);\n\n // Support scope as string options [/*title, */content]\n if(options.content) {\n $popover.$scope.content = options.content;\n }\n\n return $popover;\n\n }\n\n return PopoverFactory;\n\n };\n\n })\n\n .directive('bsPopover', function($window, $sce, $popover) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'customClass', 'autoClose', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoClose'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n });\n });\n\n // Support scope as an object\n attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);\n newValue === true ? popover.show() : popover.hide();\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n popover.setViewport(newValue);\n });\n\n // Initialize popover\n var popover = $popover(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (popover) popover.destroy();\n options = null;\n popover = null;\n });\n\n }\n };\n\n });\n\n// Source: scrollspy/scrollspy.js\nangular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', 'mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$scrollspy', function() {\n\n // Pool of registered spies\n var spies = this.$$spies = {};\n\n var defaults = this.defaults = {\n debounce: 150,\n throttle: 100,\n offset: 100\n };\n\n this.$get = function($window, $document, $rootScope, dimensions, debounce, throttle) {\n\n var windowEl = angular.element($window);\n var docEl = angular.element($document.prop('documentElement'));\n var bodyEl = angular.element($window.document.body);\n\n // Helper functions\n\n function nodeName(element, name) {\n return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();\n }\n\n function ScrollSpyFactory(config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n if(!options.element) options.element = bodyEl;\n var isWindowSpy = nodeName(options.element, 'body');\n var scrollEl = isWindowSpy ? windowEl : options.element;\n var scrollId = isWindowSpy ? 'window' : options.id;\n\n // Use existing spy\n if(spies[scrollId]) {\n spies[scrollId].$$count++;\n return spies[scrollId];\n }\n\n var $scrollspy = {};\n\n // Private vars\n var unbindViewContentLoaded, unbindIncludeContentLoaded;\n var trackedElements = $scrollspy.$trackedElements = [];\n var sortedElements = [];\n var activeTarget;\n var debouncedCheckPosition;\n var throttledCheckPosition;\n var debouncedCheckOffsets;\n var viewportHeight;\n var scrollTop;\n\n $scrollspy.init = function() {\n\n // Setup internal ref counter\n this.$$count = 1;\n\n // Bind events\n debouncedCheckPosition = debounce(this.checkPosition, options.debounce);\n throttledCheckPosition = throttle(this.checkPosition, options.throttle);\n scrollEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', debouncedCheckPosition);\n scrollEl.on('scroll', throttledCheckPosition);\n\n debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);\n unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);\n unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);\n debouncedCheckOffsets();\n\n // Register spy for reuse\n if(scrollId) {\n spies[scrollId] = $scrollspy;\n }\n\n };\n\n $scrollspy.destroy = function() {\n\n // Check internal ref counter\n this.$$count--;\n if(this.$$count > 0) {\n return;\n }\n\n // Unbind events\n scrollEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', debouncedCheckPosition);\n scrollEl.off('scroll', throttledCheckPosition);\n unbindViewContentLoaded();\n unbindIncludeContentLoaded();\n if (scrollId) {\n delete spies[scrollId];\n }\n };\n\n $scrollspy.checkPosition = function() {\n\n // Not ready yet\n if(!sortedElements.length) return;\n\n // Calculate the scroll position\n scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;\n\n // Calculate the viewport height for use by the components\n viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));\n\n // Activate first element if scroll is smaller\n if(scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {\n return $scrollspy.$activateElement(sortedElements[0]);\n }\n\n // Activate proper element\n for (var i = sortedElements.length; i--;) {\n if(angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) continue;\n if(activeTarget === sortedElements[i].target) continue;\n if(scrollTop < sortedElements[i].offsetTop) continue;\n if(sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) continue;\n return $scrollspy.$activateElement(sortedElements[i]);\n }\n\n };\n\n $scrollspy.checkPositionWithEventLoop = function() {\n // IE 9 throws an error if we use 'this' instead of '$scrollspy'\n // in this setTimeout call\n setTimeout($scrollspy.checkPosition, 1);\n };\n\n // Protected methods\n\n $scrollspy.$activateElement = function(element) {\n if(activeTarget) {\n var activeElement = $scrollspy.$getTrackedElement(activeTarget);\n if(activeElement) {\n activeElement.source.removeClass('active');\n if(nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {\n activeElement.source.parent().parent().removeClass('active');\n }\n }\n }\n activeTarget = element.target;\n element.source.addClass('active');\n if(nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {\n element.source.parent().parent().addClass('active');\n }\n };\n\n $scrollspy.$getTrackedElement = function(target) {\n return trackedElements.filter(function(obj) {\n return obj.target === target;\n })[0];\n };\n\n // Track offsets behavior\n\n $scrollspy.checkOffsets = function() {\n\n angular.forEach(trackedElements, function(trackedElement) {\n var targetElement = document.querySelector(trackedElement.target);\n trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;\n if(options.offset && trackedElement.offsetTop !== null) trackedElement.offsetTop -= options.offset * 1;\n });\n\n sortedElements = trackedElements\n .filter(function(el) {\n return el.offsetTop !== null;\n })\n .sort(function(a, b) {\n return a.offsetTop - b.offsetTop;\n });\n\n debouncedCheckPosition();\n\n };\n\n $scrollspy.trackElement = function(target, source) {\n trackedElements.push({target: target, source: source});\n };\n\n $scrollspy.untrackElement = function(target, source) {\n var toDelete;\n for (var i = trackedElements.length; i--;) {\n if(trackedElements[i].target === target && trackedElements[i].source === source) {\n toDelete = i;\n break;\n }\n }\n trackedElements = trackedElements.splice(toDelete, 1);\n };\n\n $scrollspy.activate = function(i) {\n trackedElements[i].addClass('active');\n };\n\n // Initialize plugin\n\n $scrollspy.init();\n return $scrollspy;\n\n }\n\n return ScrollSpyFactory;\n\n };\n\n })\n\n .directive('bsScrollspy', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'EAC',\n link: function postLink(scope, element, attr) {\n\n var options = {scope: scope};\n angular.forEach(['offset', 'target'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n var scrollspy = $scrollspy(options);\n scrollspy.trackElement(options.target, element);\n\n scope.$on('$destroy', function() {\n if (scrollspy) {\n scrollspy.untrackElement(options.target, element);\n scrollspy.destroy();\n }\n options = null;\n scrollspy = null;\n });\n\n }\n };\n\n })\n\n\n .directive('bsScrollspyList', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'A',\n compile: function postLink(element, attr) {\n var children = element[0].querySelectorAll('li > a[href]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));\n });\n }\n\n };\n\n });\n\n// Source: select/select.js\nangular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$select', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'select',\n prefixEvent: '$select',\n placement: 'bottom-left',\n template: 'select/select.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n multiple: false,\n allNoneButtons: false,\n sort: true,\n caretHtml: ' ',\n placeholder: 'Choose among the following...',\n allText: 'All',\n noneText: 'None',\n maxLength: 3,\n maxLengthHtml: 'selected',\n iconCheckmark: 'glyphicon glyphicon-ok'\n };\n\n this.$get = function($window, $document, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n\n function SelectFactory(element, controller, config) {\n\n var $select = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $select = $tooltip(element, options);\n var scope = $select.$scope;\n\n scope.$matches = [];\n if (options.multiple) {\n scope.$activeIndex = [];\n }\n else {\n scope.$activeIndex = -1;\n }\n scope.$isMultiple = options.multiple;\n scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n scope.$iconCheckmark = options.iconCheckmark;\n scope.$allText = options.allText;\n scope.$noneText = options.noneText;\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $select.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $select.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $select.$isVisible();\n };\n\n scope.$isActive = function(index) {\n return $select.$isActive(index);\n };\n\n scope.$selectAll = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (!scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n scope.$selectNone = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n // Public methods\n\n $select.update = function(matches) {\n scope.$matches = matches;\n $select.$updateActiveIndex();\n };\n\n $select.activate = function(index) {\n if(options.multiple) {\n $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);\n if(options.sort) scope.$activeIndex.sort();\n } else {\n scope.$activeIndex = index;\n }\n return scope.$activeIndex;\n };\n\n $select.select = function(index) {\n var value = scope.$matches[index].value;\n scope.$apply(function() {\n $select.activate(index);\n if(options.multiple) {\n controller.$setViewValue(scope.$activeIndex.map(function(index) {\n return scope.$matches[index].value;\n }));\n } else {\n controller.$setViewValue(value);\n // Hide if single select\n $select.hide();\n }\n });\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $select);\n };\n\n // Protected methods\n\n $select.$updateActiveIndex = function() {\n if(controller.$modelValue && scope.$matches.length) {\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n scope.$activeIndex = controller.$modelValue.map(function(value) {\n return $select.$getIndex(value);\n });\n } else {\n scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n }\n } else if(scope.$activeIndex >= scope.$matches.length) {\n scope.$activeIndex = options.multiple ? [] : 0;\n }\n };\n\n $select.$isVisible = function() {\n if(!options.minLength || !controller) {\n return scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && controller.$viewValue.length >= options.minLength;\n };\n\n $select.$isActive = function(index) {\n if(options.multiple) {\n return scope.$activeIndex.indexOf(index) !== -1;\n } else {\n return scope.$activeIndex === index;\n }\n };\n\n $select.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $select.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n targetEl.triggerHandler('click');\n }\n };\n\n $select.$onKeyDown = function(evt) {\n if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // release focus on tab\n if (options.multiple && evt.keyCode === 9) {\n return $select.hide();\n }\n\n // Select with enter\n if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n return $select.select(scope.$activeIndex);\n }\n\n if (!options.multiple) {\n // Navigate with keyboard\n if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 38 && scope.$activeIndex < 0) scope.$activeIndex = scope.$matches.length - 1;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n }\n };\n\n // Overrides\n\n var _show = $select.show;\n $select.show = function() {\n _show();\n if(options.multiple) {\n $select.$element.addClass('select-multiple');\n }\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $select.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $select.hide;\n $select.hide = function() {\n if(!options.multiple && !controller.$modelValue) {\n scope.$activeIndex = -1;\n }\n $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $select.$onKeyDown);\n }\n _hide(true);\n };\n\n return $select;\n\n }\n\n SelectFactory.defaults = defaults;\n return SelectFactory;\n\n };\n\n })\n\n .directive('bsSelect', function($window, $parse, $q, $select, $parseOptions) {\n\n var defaults = $select.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, placeholder: defaults.placeholder};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'placeholder', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id', 'sort', 'caretHtml', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'allNoneButtons', 'sort'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Only parse data-multiple. Angular sets existence attributes to true (multiple/required/etc), they apply this\n // to data-multiple as well for some reason, so we'll parse this ourselves and disregard multiple\n var dataMultiple = element.attr('data-multiple');\n if(angular.isDefined(dataMultiple)) {\n if(falseValueRegExp.test(dataMultiple))\n options.multiple = false;\n else\n options.multiple = dataMultiple;\n }\n\n // Add support for select markup\n if(element[0].nodeName.toLowerCase() === 'select') {\n var inputEl = element;\n inputEl.css('display', 'none');\n element = angular.element('');\n inputEl.after(element);\n }\n\n // Build proper bsOptions\n var parsedOptions = $parseOptions(attr.bsOptions);\n\n // Initialize select\n var select = $select(element, controller, options);\n\n // Watch bsOptions values before filtering for changes\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n scope.$watchCollection(watchedOptions, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n select.update(values);\n controller.$render();\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n select.$updateActiveIndex();\n controller.$render();\n }, true);\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var selected, index;\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n selected = controller.$modelValue.map(function(value) {\n index = select.$getIndex(value);\n return angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }).filter(angular.isDefined);\n if(selected.length > (options.maxLength || defaults.maxLength)) {\n selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml);\n } else {\n selected = selected.join(', ');\n }\n } else {\n index = select.$getIndex(controller.$modelValue);\n selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }\n element.html((selected ? selected : options.placeholder) + (options.caretHtml ? options.caretHtml : defaults.caretHtml));\n };\n\n if(options.multiple){\n controller.$isEmpty = function(value){\n return !value || value.length === 0;\n };\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (select) select.destroy();\n options = null;\n select = null;\n });\n\n }\n };\n\n });\n\n// Source: tab/tab.js\nangular.module('mgcrea.ngStrap.tab', [])\n\n .provider('$tab', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n template: 'tab/tab.tpl.html',\n navClass: 'nav-tabs',\n activeClass: 'active'\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'navClass', 'activeClass'], function(key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // Publish options on scope\n $scope.$navClass = self.$options.navClass;\n $scope.$activeClass = self.$options.activeClass;\n\n self.$panes = $scope.$panes = [];\n\n // Please use $activePaneChangeListeners if you use `bsActivePane`\n // Because we removed `ngModel` as default, we rename viewChangeListeners to\n // activePaneChangeListeners to make more sense.\n self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n if(angular.isUndefined(self.$panes.$active)) {\n $scope.$setActive(pane.name || 0);\n }\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var active = self.$panes.$active;\n var activeIndex;\n if(angular.isString(active)) {\n activeIndex = self.$panes.map(function(pane) {\n return pane.name;\n }).indexOf(active);\n } else {\n activeIndex = self.$panes.$active;\n }\n\n // remove pane from $panes array\n self.$panes.splice(index, 1);\n\n if (index < activeIndex) {\n // we removed a pane before the active pane, so we need to\n // decrement the active pane index\n activeIndex--;\n }\n else if (index === activeIndex && activeIndex === self.$panes.length) {\n // we remove the active pane and it was the one at the end,\n // so select the previous one\n activeIndex--;\n }\n if(activeIndex >= 0 && activeIndex < self.$panes.length) {\n self.$setActive(self.$panes[activeIndex].name || activeIndex);\n } else {\n self.$setActive();\n }\n };\n\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$activePaneChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$isActive = $scope.$isActive = function($pane, $index) {\n return self.$panes.$active === $pane.name || self.$panes.$active === $index;\n };\n\n };\n\n this.$get = function() {\n var $tab = {};\n $tab.defaults = defaults;\n $tab.controller = controller;\n return $tab;\n };\n\n })\n\n .directive('bsTabs', function($window, $animate, $tab, $parse) {\n\n var defaults = $tab.defaults;\n\n return {\n require: ['?ngModel', 'bsTabs'],\n transclude: true,\n scope: true,\n controller: ['$scope', '$element', '$attrs', $tab.controller],\n templateUrl: function(element, attr) {\n return attr.template || defaults.template;\n },\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // 'ngModel' does interfere with form validation\n // and status, use `bsActivePane` instead to avoid it\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n bsTabsCtrl.$setActive(modelValue);\n return modelValue;\n });\n\n }\n\n if (attrs.bsActivePane) {\n // adapted from angularjs ngModelController bindings\n // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n // Update bsActivePane value with change\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n });\n\n // watch bsActivePane for value changes\n scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n bsTabsCtrl.$setActive(newValue);\n }, true);\n }\n }\n };\n\n })\n\n .directive('bsPane', function($window, $animate, $sce) {\n\n return {\n require: ['^?ngModel', '^bsTabs'],\n scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // Add base class\n element.addClass('tab-pane');\n\n // Observe title attribute for change\n attrs.$observe('title', function(newValue, oldValue) {\n scope.title = $sce.trustAsHtml(newValue);\n });\n\n // Save tab name into scope\n scope.name = attrs.name;\n\n // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\n }\n\n attrs.$observe('disabled', function(newValue, oldValue) {\n scope.disabled = scope.$eval(newValue);\n });\n\n // Push pane to parent bsTabs controller\n bsTabsCtrl.$push(scope);\n\n // remove pane from tab controller when pane is destroyed\n scope.$on('$destroy', function() {\n bsTabsCtrl.$remove(scope);\n });\n\n function render() {\n var index = bsTabsCtrl.$panes.indexOf(scope);\n $animate[bsTabsCtrl.$isActive(scope, index) ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n\n// Source: timepicker/timepicker.js\nangular.module('mgcrea.ngStrap.timepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$timepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'timepicker',\n prefixClass: 'timepicker',\n placement: 'bottom-left',\n template: 'timepicker/timepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: true,\n timeType: 'date',\n timeFormat: 'shortTime',\n timezone: null,\n modelTimeFormat: null,\n autoclose: false,\n minTime: -Infinity,\n maxTime: +Infinity,\n length: 5,\n hourStep: 1,\n minuteStep: 5,\n secondStep: 5,\n roundDisplay: false,\n iconUp: 'glyphicon glyphicon-chevron-up',\n iconDown: 'glyphicon glyphicon-chevron-down',\n arrowBehavior: 'pager'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function timepickerFactory(element, controller, config) {\n\n var $timepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $timepicker.$options;\n var scope = $timepicker.$scope;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n function floorMinutes(time)\n {\n // coeff used to floor current time to nearest minuteStep interval\n var coeff = 1000 * 60 * options.minuteStep;\n return new Date(Math.floor(time.getTime() / coeff) * coeff);\n }\n\n // View vars\n\n var selectedIndex = 0;\n var defaultDate = options.roundDisplay ? floorMinutes(new Date()) : new Date();\n var startDate = controller.$dateValue || defaultDate;\n var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n var hoursFormat = $dateFormatter.hoursFormat(format),\n timeSeparator = $dateFormatter.timeSeparator(format),\n minutesFormat = $dateFormatter.minutesFormat(format),\n secondsFormat = $dateFormatter.secondsFormat(format),\n showSeconds = $dateFormatter.showSeconds(format),\n showAM = $dateFormatter.showAM(format);\n\n scope.$iconUp = options.iconUp;\n scope.$iconDown = options.iconDown;\n\n // Scope methods\n\n scope.$select = function(date, index) {\n $timepicker.select(date, index);\n };\n scope.$moveIndex = function(value, index) {\n $timepicker.$moveIndex(value, index);\n };\n scope.$switchMeridian = function(date) {\n $timepicker.switchMeridian(date);\n };\n\n // Public methods\n\n $timepicker.update = function(date) {\n // console.warn('$timepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $timepicker.$date = date;\n angular.extend(viewDate, {hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds(), millisecond: date.getMilliseconds()});\n $timepicker.$build();\n } else if(!$timepicker.$isBuilt) {\n $timepicker.$build();\n }\n };\n\n $timepicker.select = function(date, index, keep) {\n // console.warn('$timepicker.select', date, scope.$mode);\n if(!controller.$dateValue || isNaN(controller.$dateValue.getTime())) controller.$dateValue = new Date(1970, 0, 1);\n if(!angular.isDate(date)) date = new Date(date);\n if(index === 0) controller.$dateValue.setHours(date.getHours());\n else if(index === 1) controller.$dateValue.setMinutes(date.getMinutes());\n else if(index === 2) controller.$dateValue.setSeconds(date.getSeconds());\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $timepicker.hide(true); });\n }\n };\n\n $timepicker.switchMeridian = function(date) {\n if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) {\n return;\n }\n var hours = (date || controller.$dateValue).getHours();\n controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12);\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n };\n\n // Protected methods\n\n $timepicker.$build = function() {\n // console.warn('$timepicker.$build() viewDate=%o', viewDate);\n var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n var hours = [], hour;\n for(i = 0; i < options.length; i++) {\n hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);\n hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});\n }\n var minutes = [], minute;\n for(i = 0; i < options.length; i++) {\n minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);\n minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n }\n var seconds = [], second;\n for(i = 0; i < options.length; i++) {\n second = new Date(1970, 0, 1, 0, 0, viewDate.second - (midIndex - i) * options.secondStep);\n seconds.push({date: second, label: formatDate(second, secondsFormat), selected: $timepicker.$date && $timepicker.$isSelected(second, 2), disabled: $timepicker.$isDisabled(second, 2)});\n }\n\n var rows = [];\n for(i = 0; i < options.length; i++) {\n if (showSeconds) {\n rows.push([hours[i], minutes[i], seconds[i]]);\n } else {\n rows.push([hours[i], minutes[i]]);\n }\n }\n scope.rows = rows;\n scope.showSeconds = showSeconds;\n scope.showAM = showAM;\n scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n scope.timeSeparator = timeSeparator;\n $timepicker.$isBuilt = true;\n };\n\n $timepicker.$isSelected = function(date, index) {\n if(!$timepicker.$date) return false;\n else if(index === 0) {\n return date.getHours() === $timepicker.$date.getHours();\n } else if(index === 1) {\n return date.getMinutes() === $timepicker.$date.getMinutes();\n } else if(index === 2) {\n return date.getSeconds() === $timepicker.$date.getSeconds();\n }\n };\n\n $timepicker.$isDisabled = function(date, index) {\n var selectedTime;\n if(index === 0) {\n selectedTime = date.getTime() + viewDate.minute * 6e4 + viewDate.second * 1e3;\n } else if(index === 1) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.second * 1e3;\n } else if(index === 2) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.minute * 6e4;\n }\n return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1;\n };\n\n scope.$arrowAction = function (value, index) {\n if (options.arrowBehavior === 'picker') {\n $timepicker.$setTimeByStep(value,index);\n } else {\n $timepicker.$moveIndex(value,index);\n }\n };\n\n $timepicker.$setTimeByStep = function(value, index) {\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n if (index === 0) {\n newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n }\n else if (index === 1) {\n newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\n }\n else if (index === 2) {\n newDate.setSeconds(seconds - (parseInt(options.secondStep, 10) * value));\n }\n $timepicker.select(newDate, index, true);\n };\n\n $timepicker.$moveIndex = function(value, index) {\n var targetDate;\n if(index === 0) {\n targetDate = new Date(1970, 0, 1, viewDate.hour + (value * options.length), viewDate.minute, viewDate.second);\n angular.extend(viewDate, {hour: targetDate.getHours()});\n } else if(index === 1) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + (value * options.length * options.minuteStep), viewDate.second);\n angular.extend(viewDate, {minute: targetDate.getMinutes()});\n } else if(index === 2) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute, viewDate.second + (value * options.length * options.secondStep));\n angular.extend(viewDate, {second: targetDate.getSeconds()});\n }\n $timepicker.$build();\n };\n\n $timepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n if(evt.target.nodeName.toLowerCase() !== 'input') evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $timepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Close on enter\n if(evt.keyCode === 13) return $timepicker.hide(true);\n\n // Navigate with keyboard\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n var sepLength = 1;\n var lateralMove = /(37|39)/.test(evt.keyCode);\n var count = 2 + showSeconds * 1 + showAM * 1;\n\n // Navigate indexes (left, right)\n if (lateralMove) {\n if(evt.keyCode === 37) selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1;\n else if(evt.keyCode === 39) selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0;\n }\n\n // Update values (up, down)\n var selectRange = [0, hoursLength];\n var incr = 0;\n if (evt.keyCode === 38) incr = -1;\n if (evt.keyCode === 40) incr = +1;\n var isSeconds = selectedIndex === 2 && showSeconds;\n var isMeridian = selectedIndex === 2 && !showSeconds || selectedIndex === 3 && showSeconds;\n if(selectedIndex === 0) {\n newDate.setHours(hours + incr*parseInt(options.hourStep, 10));\n // re-calculate hours length because we have changed hours value\n hoursLength = formatDate(newDate, hoursFormat).length;\n selectRange = [0, hoursLength];\n } else if(selectedIndex === 1) {\n newDate.setMinutes(minutes + incr*parseInt(options.minuteStep, 10));\n // re-calculate minutes length because we have changes minutes value\n minutesLength = formatDate(newDate, minutesFormat).length;\n selectRange = [hoursLength + sepLength, minutesLength];\n } else if(isSeconds) {\n newDate.setSeconds(seconds + incr*parseInt(options.secondStep, 10));\n // re-calculate seconds length because we have changes seconds value\n secondsLength = formatDate(newDate, secondsFormat).length;\n selectRange = [hoursLength + sepLength + minutesLength + sepLength, secondsLength];\n } else if(isMeridian) {\n if(!lateralMove) $timepicker.switchMeridian();\n selectRange = [hoursLength + sepLength + minutesLength + sepLength + (secondsLength + sepLength)*showSeconds, 2];\n }\n $timepicker.select(newDate, selectedIndex, true);\n createSelection(selectRange[0], selectRange[1]);\n parentScope.$digest();\n };\n\n // Private\n\n function createSelection(start, length) {\n var end = start + length;\n if(element[0].createTextRange) {\n var selRange = element[0].createTextRange();\n selRange.collapse(true);\n selRange.moveStart('character', start);\n selRange.moveEnd('character', end);\n selRange.select();\n } else if(element[0].setSelectionRange) {\n element[0].setSelectionRange(start, end);\n } else if(angular.isUndefined(element[0].selectionStart)) {\n element[0].selectionStart = start;\n element[0].selectionEnd = end;\n }\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $timepicker.init;\n $timepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'time');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $timepicker.destroy;\n $timepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $timepicker.show;\n $timepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $timepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $timepicker.hide;\n $timepicker.hide = function(blur) {\n if(!$timepicker.$isShown) return;\n $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $timepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $timepicker;\n\n }\n\n timepickerFactory.defaults = defaults;\n return timepickerFactory;\n\n };\n\n })\n\n\n .directive('bsTimepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n var defaults = $timepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'timeType', 'timeFormat', 'timezone', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'secondStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'roundDisplay', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative', 'roundDisplay'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!timepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(timepicker),?/i);\n newValue === true ? timepicker.show() : timepicker.hide();\n });\n\n // Initialize timepicker\n if(isNative && (options.useNative || defaults.useNative)) options.timeFormat = 'HH:mm';\n var timepicker = $timepicker(element, controller, options);\n options = timepicker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n // Initialize parser\n var dateParser = $dateParser({format: options.timeFormat, lang: lang});\n\n // Observe attributes for changes\n angular.forEach(['minTime', 'maxTime'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n !isNaN(timepicker.$options[key]) && timepicker.$build();\n validateAgainstMinMaxTime(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue);\n timepicker.update(controller.$dateValue);\n }, true);\n\n function validateAgainstMinMaxTime(parsedTime) {\n if (!angular.isDate(parsedTime)) return;\n var isMinValid = isNaN(options.minTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) >= options.minTime;\n var isMaxValid = isNaN(options.maxTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) <= options.maxTime;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(!isValid) {\n return;\n }\n controller.$dateValue = parsedTime;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n controller.$setValidity('date', true);\n return null;\n }\n var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedTime || isNaN(parsedTime.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxTime(parsedTime);\n }\n\n if(options.timeType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedTime, options.timezone, true);\n return formatDate(date, options.modelTimeFormat || options.timeFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.timeType === 'number') {\n return date.getTime();\n } else if(options.timeType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.timeType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.timeType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelTimeFormat);\n } else if(options.timeType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5);\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getTimeFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getTimeFormattedString());\n };\n\n function getTimeFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (timepicker) timepicker.destroy();\n options = null;\n timepicker = null;\n });\n\n }\n };\n\n });\n\n// Source: tooltip/tooltip.js\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$tooltip', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n prefixClass: 'tooltip',\n prefixEvent: 'tooltip',\n container: false,\n target: false,\n placement: 'top',\n template: 'tooltip/tooltip.tpl.html',\n contentTemplate: false,\n trigger: 'hover focus',\n keyboard: false,\n html: false,\n show: false,\n title: '',\n type: '',\n delay: 0,\n autoClose: false,\n bsEnabled: true,\n viewport: {\n selector: 'body',\n padding: 0\n }\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n var trim = String.prototype.trim;\n var isTouch = 'createTouch' in $window.document;\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n var $body = angular.element($window.document);\n\n function TooltipFactory(element, config) {\n\n var $tooltip = {};\n\n // Common vars\n var nodeName = element[0].nodeName.toLowerCase();\n var options = $tooltip.$options = angular.extend({}, defaults, config);\n $tooltip.$promise = fetchTemplate(options.template);\n var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(options.delay && angular.isString(options.delay)) {\n var split = options.delay.split(',').map(parseFloat);\n options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $tooltip.$id = options.id || element.attr('id') || '';\n\n // Support scope as string options\n if(options.title) {\n scope.title = $sce.trustAsHtml(options.title);\n }\n\n // Provide scope helpers\n scope.$setEnabled = function(isEnabled) {\n scope.$$postDigest(function() {\n $tooltip.setEnabled(isEnabled);\n });\n };\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $tooltip.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $tooltip.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $tooltip.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $tooltip.$isShown = scope.$isShown = false;\n\n // Private vars\n var timeout, hoverState;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $tooltip.$promise = $tooltip.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]);\n if(!contentEl.length) contentEl = findElement('[ng-bind=\"title\"]', templateEl[0]);\n contentEl.removeAttr('ng-bind').html(contentTemplate);\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize tooltip\n var tipLinker, tipElement, tipTemplate, tipContainer, tipScope;\n $tooltip.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n tipTemplate = template;\n tipLinker = $compile(template);\n $tooltip.init();\n });\n\n $tooltip.init = function() {\n\n // Options: delay\n if (options.delay && angular.isNumber(options.delay)) {\n options.delay = {\n show: options.delay,\n hide: options.delay\n };\n }\n\n // Replace trigger on touch devices ?\n // if(isTouch && options.trigger === defaults.trigger) {\n // options.trigger.replace(/hover/g, 'click');\n // }\n\n // Options : container\n if(options.container === 'self') {\n tipContainer = element;\n } else if(angular.isElement(options.container)) {\n tipContainer = options.container;\n } else if(options.container) {\n tipContainer = findElement(options.container);\n }\n\n // Options: trigger\n bindTriggerEvents();\n\n // Options: target\n if(options.target) {\n options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n }\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n options.trigger === 'focus' ? element[0].focus() : $tooltip.show();\n });\n }\n\n };\n\n $tooltip.destroy = function() {\n\n // Unbind events\n unbindTriggerEvents();\n\n // Remove element\n destroyTipElement();\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $tooltip.enter = function() {\n\n clearTimeout(timeout);\n hoverState = 'in';\n if (!options.delay || !options.delay.show) {\n return $tooltip.show();\n }\n\n timeout = setTimeout(function() {\n if (hoverState ==='in') $tooltip.show();\n }, options.delay.show);\n\n };\n\n $tooltip.show = function() {\n if (!options.bsEnabled || $tooltip.$isShown) return;\n\n scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n var parent, after;\n if (options.container) {\n parent = tipContainer;\n if (tipContainer[0].lastChild) {\n after = angular.element(tipContainer[0].lastChild);\n } else {\n after = null;\n }\n } else {\n parent = null;\n after = element;\n }\n\n\n // Hide any existing tipElement\n if(tipElement) destroyTipElement();\n // Fetch a cloned element linked from template\n tipScope = $tooltip.$scope.$new();\n tipElement = $tooltip.$element = tipLinker(tipScope, function(clonedElement, scope) {});\n\n // Set the initial positioning. Make the tooltip invisible\n // so IE doesn't try to focus on it off screen.\n tipElement.css({top: '-9999px', left: '-9999px', right: 'auto', display: 'block', visibility: 'hidden'});\n\n // Options: animation\n if(options.animation) tipElement.addClass(options.animation);\n // Options: type\n if(options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n // Options: custom classes\n if(options.customClass) tipElement.addClass(options.customClass);\n\n // Append the element, without any animations. If we append\n // using $animate.enter, some of the animations cause the placement\n // to be off due to the transforms.\n after ? after.after(tipElement) : parent.prepend(tipElement);\n\n $tooltip.$isShown = scope.$isShown = true;\n safeDigest(scope);\n\n // Now, apply placement\n $tooltip.$applyPlacement();\n\n // Once placed, animate it.\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.enter(tipElement, parent, after, enterAnimateCallback);\n if(promise && promise.then) promise.then(enterAnimateCallback);\n safeDigest(scope);\n\n $$rAF(function () {\n // Once the tooltip is placed and the animation starts, make the tooltip visible\n if(tipElement) tipElement.css({visibility: 'visible'});\n });\n\n // Bind events\n if(options.keyboard) {\n if(options.trigger !== 'focus') {\n $tooltip.focus();\n }\n bindKeyboardEvents();\n }\n\n if(options.autoClose) {\n bindAutoCloseEvents();\n }\n\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $tooltip);\n }\n\n $tooltip.leave = function() {\n\n clearTimeout(timeout);\n hoverState = 'out';\n if (!options.delay || !options.delay.hide) {\n return $tooltip.hide();\n }\n timeout = setTimeout(function () {\n if (hoverState === 'out') {\n $tooltip.hide();\n }\n }, options.delay.hide);\n\n };\n\n var _blur;\n var _tipToHide;\n $tooltip.hide = function(blur) {\n\n if(!$tooltip.$isShown) return;\n scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n\n // store blur value for leaveAnimateCallback to use\n _blur = blur;\n\n // store current tipElement reference to use\n // in leaveAnimateCallback\n _tipToHide = tipElement;\n\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.leave(tipElement, leaveAnimateCallback);\n if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n $tooltip.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.keyboard && tipElement !== null) {\n unbindKeyboardEvents();\n }\n\n if(options.autoClose && tipElement !== null) {\n unbindAutoCloseEvents();\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\n\n // check if current tipElement still references\n // the same element when hide was called\n if (tipElement === _tipToHide) {\n // Allow to blur the input when hidden, like when pressing enter key\n if(_blur && options.trigger === 'focus') {\n return element[0].blur();\n }\n\n // clean up child scopes\n destroyTipElement();\n }\n }\n\n $tooltip.toggle = function() {\n $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter();\n };\n\n $tooltip.focus = function() {\n tipElement[0].focus();\n };\n\n $tooltip.setEnabled = function(isEnabled) {\n options.bsEnabled = isEnabled;\n };\n\n $tooltip.setViewport = function(viewport) {\n options.viewport = viewport;\n };\n\n // Protected methods\n\n $tooltip.$applyPlacement = function() {\n if(!tipElement) return;\n\n // Determine if we're doing an auto or normal placement\n var placement = options.placement,\n autoToken = /\\s?auto?\\s?/i,\n autoPlace = autoToken.test(placement);\n\n if (autoPlace) {\n placement = placement.replace(autoToken, '') || defaults.placement;\n }\n\n // Need to add the position class before we get\n // the offsets\n tipElement.addClass(options.placement);\n\n // Get the position of the target element\n // and the height and width of the tooltip so we can center it.\n var elementPosition = getPosition(),\n tipWidth = tipElement.prop('offsetWidth'),\n tipHeight = tipElement.prop('offsetHeight');\n\n // If we're auto placing, we need to check the positioning\n if (autoPlace) {\n var originalPlacement = placement;\n var container = options.container ? findElement(options.container) : element.parent();\n var containerPosition = getPosition(container);\n\n // Determine if the vertical placement\n if (originalPlacement.indexOf('bottom') >= 0 && elementPosition.bottom + tipHeight > containerPosition.bottom) {\n placement = originalPlacement.replace('bottom', 'top');\n } else if (originalPlacement.indexOf('top') >= 0 && elementPosition.top - tipHeight < containerPosition.top) {\n placement = originalPlacement.replace('top', 'bottom');\n }\n\n // Determine the horizontal placement\n // The exotic placements of left and right are opposite of the standard placements. Their arrows are put on the left/right\n // and flow in the opposite direction of their placement.\n if ((originalPlacement === 'right' || originalPlacement === 'bottom-left' || originalPlacement === 'top-left') &&\n elementPosition.right + tipWidth > containerPosition.width) {\n\n placement = originalPlacement === 'right' ? 'left' : placement.replace('left', 'right');\n } else if ((originalPlacement === 'left' || originalPlacement === 'bottom-right' || originalPlacement === 'top-right') &&\n elementPosition.left - tipWidth < containerPosition.left) {\n\n placement = originalPlacement === 'left' ? 'right' : placement.replace('right', 'left');\n }\n\n tipElement.removeClass(originalPlacement).addClass(placement);\n }\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n applyPlacement(tipPosition, placement);\n };\n\n $tooltip.$onKeyUp = function(evt) {\n if (evt.which === 27 && $tooltip.$isShown) {\n $tooltip.hide();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusKeyUp = function(evt) {\n if (evt.which === 27) {\n element[0].blur();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusElementMouseDown = function(evt) {\n evt.preventDefault();\n evt.stopPropagation();\n // Some browsers do not auto-focus buttons (eg. Safari)\n $tooltip.$isShown ? element[0].blur() : element[0].focus();\n };\n\n // bind/unbind events\n function bindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n angular.forEach(triggers, function(trigger) {\n if(trigger === 'click') {\n element.on('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n });\n }\n\n function unbindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n for (var i = triggers.length; i--;) {\n var trigger = triggers[i];\n if(trigger === 'click') {\n element.off('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n }\n }\n\n function bindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.on('keyup', $tooltip.$onKeyUp);\n } else {\n element.on('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n function unbindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.off('keyup', $tooltip.$onKeyUp);\n } else {\n element.off('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n var _autoCloseEventsBinded = false;\n function bindAutoCloseEvents() {\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // Stop propagation when clicking inside tooltip\n tipElement.on('click', stopEventPropagation);\n\n // Hide when clicking outside tooltip\n $body.on('click', $tooltip.hide);\n\n _autoCloseEventsBinded = true;\n }, 0, false);\n }\n\n function unbindAutoCloseEvents() {\n if (_autoCloseEventsBinded) {\n tipElement.off('click', stopEventPropagation);\n $body.off('click', $tooltip.hide);\n _autoCloseEventsBinded = false;\n }\n }\n\n function stopEventPropagation(event) {\n event.stopPropagation();\n }\n\n // Private methods\n\n function getPosition($element) {\n $element = $element || (options.target || element);\n\n var el = $element[0],\n isBody = el.tagName === 'BODY';\n\n var elRect = el.getBoundingClientRect();\n var rect = {};\n\n // IE8 has issues with angular.extend and using elRect directly.\n // By coping the values of elRect into a new object, we can continue to use extend\n for (var p in elRect) {\n // DO NOT use hasOwnProperty when inspecting the return of getBoundingClientRect.\n rect[p] = elRect[p];\n }\n\n if (rect.width === null) {\n // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n rect = angular.extend({}, rect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });\n }\n var elOffset = isBody ? { top: 0, left: 0 } : dimensions.offset(el),\n scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.prop('scrollTop') || 0 },\n outerDims = isBody ? { width: document.documentElement.clientWidth, height: $window.innerHeight } : null;\n\n return angular.extend({}, rect, scroll, outerDims, elOffset);\n }\n\n function getCalculatedOffset(placement, position, actualWidth, actualHeight) {\n var offset;\n var split = placement.split('-');\n\n switch (split[0]) {\n case 'right':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left + position.width\n };\n break;\n case 'bottom':\n offset = {\n top: position.top + position.height,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n case 'left':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left - actualWidth\n };\n break;\n default:\n offset = {\n top: position.top - actualHeight,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n }\n\n if(!split[1]) {\n return offset;\n }\n\n // Add support for corners @todo css\n if(split[0] === 'top' || split[0] === 'bottom') {\n switch (split[1]) {\n case 'left':\n offset.left = position.left;\n break;\n case 'right':\n offset.left = position.left + position.width - actualWidth;\n }\n } else if(split[0] === 'left' || split[0] === 'right') {\n switch (split[1]) {\n case 'top':\n offset.top = position.top - actualHeight;\n break;\n case 'bottom':\n offset.top = position.top + position.height;\n }\n }\n\n return offset;\n }\n\n function applyPlacement(offset, placement) {\n var tip = tipElement[0],\n width = tip.offsetWidth,\n height = tip.offsetHeight;\n\n // manually read margins because getBoundingClientRect includes difference\n var marginTop = parseInt(dimensions.css(tip, 'margin-top'), 10),\n marginLeft = parseInt(dimensions.css(tip, 'margin-left'), 10);\n\n // we must check for NaN for ie 8/9\n if (isNaN(marginTop)) marginTop = 0;\n if (isNaN(marginLeft)) marginLeft = 0;\n\n offset.top = offset.top + marginTop;\n offset.left = offset.left + marginLeft;\n\n // dimensions setOffset doesn't round pixel values\n // so we use setOffset directly with our own function\n dimensions.setOffset(tip, angular.extend({\n using: function (props) {\n tipElement.css({\n top: Math.round(props.top) + 'px',\n left: Math.round(props.left) + 'px',\n right: ''\n });\n }\n }, offset), 0);\n\n // check to see if placing tip in new offset caused the tip to resize itself\n var actualWidth = tip.offsetWidth,\n actualHeight = tip.offsetHeight;\n\n if (placement === 'top' && actualHeight !== height) {\n offset.top = offset.top + height - actualHeight;\n }\n\n // If it's an exotic placement, exit now instead of\n // applying a delta and changing the arrow\n if (/top-left|top-right|bottom-left|bottom-right/.test(placement)) return;\n\n var delta = getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);\n\n if (delta.left) {\n offset.left += delta.left;\n } else {\n offset.top += delta.top;\n }\n\n dimensions.setOffset(tip, offset);\n\n if (/top|right|bottom|left/.test(placement)) {\n var isVertical = /top|bottom/.test(placement),\n arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight,\n arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';\n\n replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical);\n }\n }\n\n function getViewportAdjustedDelta(placement, position, actualWidth, actualHeight) {\n var delta = { top: 0, left: 0 },\n $viewport = options.viewport && findElement(options.viewport.selector || options.viewport);\n\n if (!$viewport) {\n return delta;\n }\n\n var viewportPadding = options.viewport && options.viewport.padding || 0,\n viewportDimensions = getPosition($viewport);\n\n if (/right|left/.test(placement)) {\n var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll,\n bottomEdgeOffset = position.top + viewportPadding - viewportDimensions.scroll + actualHeight;\n if (topEdgeOffset < viewportDimensions.top) { // top overflow\n delta.top = viewportDimensions.top - topEdgeOffset;\n } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;\n }\n } else {\n var leftEdgeOffset = position.left - viewportPadding,\n rightEdgeOffset = position.left + viewportPadding + actualWidth;\n if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n delta.left = viewportDimensions.left - leftEdgeOffset;\n } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow\n delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;\n }\n }\n\n return delta;\n }\n\n function replaceArrow(delta, dimension, isHorizontal) {\n var $arrow = findElement('.tooltip-arrow, .arrow', tipElement[0]);\n\n $arrow.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')\n .css(isHorizontal ? 'top' : 'left', '');\n }\n\n function destroyTipElement() {\n // Cancel pending callbacks\n clearTimeout(timeout);\n\n if($tooltip.$isShown && tipElement !== null) {\n if(options.autoClose) {\n unbindAutoCloseEvents();\n }\n\n if(options.keyboard) {\n unbindKeyboardEvents();\n }\n }\n\n if(tipScope) {\n tipScope.$destroy();\n tipScope = null;\n }\n\n if(tipElement) {\n tipElement.remove();\n tipElement = $tooltip.$element = null;\n }\n }\n\n return $tooltip;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return TooltipFactory;\n\n };\n\n })\n\n .directive('bsTooltip', function($window, $location, $sce, $tooltip, $$rAF) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Observe scope attributes for change\n attr.$observe('title', function(newValue) {\n if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n var oldValue = scope.title;\n scope.title = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }\n });\n\n // Support scope as an object\n attr.bsTooltip && scope.$watch(attr.bsTooltip, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.title = newValue;\n }\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n newValue === true ? tooltip.show() : tooltip.hide();\n });\n\n // Enabled binding support\n attr.bsEnabled && scope.$watch(attr.bsEnabled, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n newValue === false ? tooltip.setEnabled(false) : tooltip.setEnabled(true);\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n tooltip.setViewport(newValue);\n });\n\n // Initialize popover\n var tooltip = $tooltip(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(tooltip) tooltip.destroy();\n options = null;\n tooltip = null;\n });\n\n }\n };\n\n });\n\n// Source: typeahead/typeahead.js\nangular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$typeahead', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'typeahead',\n prefixEvent: '$typeahead',\n placement: 'bottom-left',\n template: 'typeahead/typeahead.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n minLength: 1,\n filter: 'filter',\n limit: 6,\n autoSelect: false,\n comparator: '',\n trimValue: true\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n\n function TypeaheadFactory(element, controller, config) {\n\n var $typeahead = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $typeahead = $tooltip(element, options);\n var parentScope = config.scope;\n var scope = $typeahead.$scope;\n\n scope.$resetMatches = function(){\n scope.$matches = [];\n scope.$activeIndex = options.autoSelect ? 0 : -1; // If set to 0, the first match will be highlighted\n };\n scope.$resetMatches();\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $typeahead.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $typeahead.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $typeahead.$isVisible();\n };\n\n // Public methods\n\n $typeahead.update = function(matches) {\n scope.$matches = matches;\n if(scope.$activeIndex >= matches.length) {\n scope.$activeIndex = options.autoSelect ? 0: -1;\n }\n\n // When the placement is not one of the bottom placements, re-calc the positioning\n // so the results render correctly.\n if (/^(bottom|bottom-left|bottom-right)$/.test(options.placement)) return;\n\n // wrap in a $timeout so the results are updated\n // before repositioning\n $timeout($typeahead.$applyPlacement);\n };\n\n $typeahead.activate = function(index) {\n scope.$activeIndex = index;\n };\n\n $typeahead.select = function(index) {\n if(index === -1) return;\n var value = scope.$matches[index].value;\n // console.log('$setViewValue', value);\n controller.$setViewValue(value);\n controller.$render();\n scope.$resetMatches();\n if(parentScope) parentScope.$digest();\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $typeahead);\n };\n\n // Protected methods\n\n $typeahead.$isVisible = function() {\n if(!options.minLength || !controller) {\n return !!scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength;\n };\n\n $typeahead.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $typeahead.$onMouseDown = function(evt) {\n // Prevent blur on mousedown\n evt.preventDefault();\n evt.stopPropagation();\n };\n\n $typeahead.$onKeyDown = function(evt) {\n if(!/(38|40|13)/.test(evt.keyCode)) return;\n\n // Let ngSubmit pass if the typeahead tip is hidden or no option is selected\n if($typeahead.$isVisible() && !(evt.keyCode === 13 && scope.$activeIndex === -1)) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n // Select with enter\n if(evt.keyCode === 13 && scope.$matches.length) {\n $typeahead.select(scope.$activeIndex);\n }\n\n // Navigate with keyboard\n else if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n };\n\n // Overrides\n\n var show = $typeahead.show;\n $typeahead.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $typeahead.$onKeyDown);\n }\n }, 0, false);\n };\n\n var hide = $typeahead.hide;\n $typeahead.hide = function() {\n $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $typeahead.$onKeyDown);\n }\n if(!options.autoSelect)\n $typeahead.activate(-1);\n hide();\n };\n\n return $typeahead;\n\n }\n\n TypeaheadFactory.defaults = defaults;\n return TypeaheadFactory;\n\n };\n\n })\n\n .directive('bsTypeahead', function($window, $parse, $q, $typeahead, $parseOptions) {\n\n var defaults = $typeahead.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'filter', 'limit', 'minLength', 'watchOptions', 'selectMode', 'autoSelect', 'comparator', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'trimValue'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n });\n\n // Disable browser autocompletion\n element.attr('autocomplete' ,'off');\n\n // Build proper bsOptions\n var filter = options.filter || defaults.filter;\n var limit = options.limit || defaults.limit;\n var comparator = options.comparator || defaults.comparator;\n\n var bsOptions = attr.bsOptions;\n if(filter) bsOptions += ' | ' + filter + ':$viewValue';\n if (comparator) bsOptions += ':' + comparator;\n if(limit) bsOptions += ' | limitTo:' + limit;\n var parsedOptions = $parseOptions(bsOptions);\n\n // Initialize typeahead\n var typeahead = $typeahead(element, controller, options);\n\n // Watch options on demand\n if(options.watchOptions) {\n // Watch bsOptions values before filtering for changes, drop function calls\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n scope.$watchCollection(watchedOptions, function (newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller).then(function (values) {\n typeahead.update(values);\n controller.$render();\n });\n });\n }\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('$watch', element.attr('ng-model'), newValue);\n scope.$modelValue = newValue; // Publish modelValue on scope for custom templates\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n // Prevent input with no future prospect if selectMode is truthy\n // @TODO test selectMode\n if(options.selectMode && !values.length && newValue.length > 0) {\n controller.$setViewValue(controller.$viewValue.substring(0, controller.$viewValue.length - 1));\n return;\n }\n if(values.length > limit) values = values.slice(0, limit);\n var isVisible = typeahead.$isVisible();\n isVisible && typeahead.update(values);\n // Do not re-queue an update if a correct value has been selected\n if(values.length === 1 && values[0].value === newValue) return;\n !isVisible && typeahead.update(values);\n // Queue a new rendering that will leverage collection loading\n controller.$render();\n });\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var displayValue = parsedOptions.displayValue(modelValue);\n return displayValue === undefined ? '' : displayValue;\n });\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n if(controller.$isEmpty(controller.$viewValue)) return element.val('');\n var index = typeahead.$getIndex(controller.$modelValue);\n var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;\n selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;\n var value = selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '') : '';\n element.val(options.trimValue === false ? value : value.trim());\n };\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (typeahead) typeahead.destroy();\n options = null;\n typeahead = null;\n });\n\n }\n };\n\n });\n\n})(window, document);\n","'use strict';\n\nangular.module('mgcrea.ngStrap.affix', ['mgcrea.ngStrap.helpers.dimensions', 'mgcrea.ngStrap.helpers.debounce'])\n\n .provider('$affix', function() {\n\n var defaults = this.defaults = {\n offsetTop: 'auto',\n inlineStyles: true\n };\n\n this.$get = function($window, debounce, dimensions) {\n\n var bodyEl = angular.element($window.document.body);\n var windowEl = angular.element($window);\n\n function AffixFactory(element, config) {\n\n var $affix = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var targetEl = options.target;\n\n // Initial private vars\n var reset = 'affix affix-top affix-bottom',\n setWidth = false,\n initialAffixTop = 0,\n initialOffsetTop = 0,\n offsetTop = 0,\n offsetBottom = 0,\n affixed = null,\n unpin = null;\n\n var parent = element.parent();\n // Options: custom parent\n if (options.offsetParent) {\n if (options.offsetParent.match(/^\\d+$/)) {\n for (var i = 0; i < (options.offsetParent * 1) - 1; i++) {\n parent = parent.parent();\n }\n }\n else {\n parent = angular.element(options.offsetParent);\n }\n }\n\n $affix.init = function() {\n\n this.$parseOffsets();\n initialOffsetTop = dimensions.offset(element[0]).top + initialAffixTop;\n setWidth = !element[0].style.width;\n\n // Bind events\n targetEl.on('scroll', this.checkPosition);\n targetEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', this.$debouncedOnResize);\n\n // Both of these checkPosition() calls are necessary for the case where\n // the user hits refresh after scrolling to the bottom of the page.\n this.checkPosition();\n this.checkPositionWithEventLoop();\n\n };\n\n $affix.destroy = function() {\n\n // Unbind events\n targetEl.off('scroll', this.checkPosition);\n targetEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', this.$debouncedOnResize);\n\n };\n\n $affix.checkPositionWithEventLoop = function() {\n\n // IE 9 throws an error if we use 'this' instead of '$affix'\n // in this setTimeout call\n setTimeout($affix.checkPosition, 1);\n\n };\n\n $affix.checkPosition = function() {\n // if (!this.$element.is(':visible')) return\n\n var scrollTop = getScrollTop();\n var position = dimensions.offset(element[0]);\n var elementHeight = dimensions.height(element[0]);\n\n // Get required affix class according to position\n var affix = getRequiredAffixClass(unpin, position, elementHeight);\n\n // Did affix status changed this last check?\n if(affixed === affix) return;\n affixed = affix;\n\n // Add proper affix class\n element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\n\n if(affix === 'top') {\n unpin = null;\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', '');\n }\n } else if(affix === 'bottom') {\n if (options.offsetUnpin) {\n unpin = -(options.offsetUnpin * 1);\n }\n else {\n // Calculate unpin threshold when affixed to bottom.\n // Hopefully the browser scrolls pixel by pixel.\n unpin = position.top - scrollTop;\n }\n if(setWidth) {\n element.css('width', '');\n }\n if (options.inlineStyles) {\n element.css('position', (options.offsetParent) ? '' : 'relative');\n element.css('top', (options.offsetParent) ? '' : ((bodyEl[0].offsetHeight - offsetBottom - elementHeight - initialOffsetTop) + 'px'));\n }\n } else { // affix === 'middle'\n unpin = null;\n if(setWidth) {\n element.css('width', element[0].offsetWidth + 'px');\n }\n if (options.inlineStyles) {\n element.css('position', 'fixed');\n element.css('top', initialAffixTop + 'px');\n }\n }\n\n };\n\n $affix.$onResize = function() {\n $affix.$parseOffsets();\n $affix.checkPosition();\n };\n $affix.$debouncedOnResize = debounce($affix.$onResize, 50);\n\n $affix.$parseOffsets = function() {\n var initialPosition = element.css('position');\n // Reset position to calculate correct offsetTop\n if (options.inlineStyles){\n element.css('position', (options.offsetParent) ? '' : 'relative');\n }\n\n if(options.offsetTop) {\n if(options.offsetTop === 'auto') {\n options.offsetTop = '+0';\n }\n if(options.offsetTop.match(/^[-+]\\d+$/)) {\n initialAffixTop = - options.offsetTop * 1;\n if(options.offsetParent) {\n offsetTop = dimensions.offset(parent[0]).top + (options.offsetTop * 1);\n }\n else {\n offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\n }\n }\n else {\n offsetTop = options.offsetTop * 1;\n }\n }\n\n if(options.offsetBottom) {\n if(options.offsetParent && options.offsetBottom.match(/^[-+]\\d+$/)) {\n // add 1 pixel due to rounding problems...\n offsetBottom = getScrollHeight() - (dimensions.offset(parent[0]).top + dimensions.height(parent[0])) + (options.offsetBottom * 1) + 1;\n }\n else {\n offsetBottom = options.offsetBottom * 1;\n }\n }\n\n // Bring back the element's position after calculations\n if (options.inlineStyles){\n element.css('position', initialPosition);\n }\n };\n\n // Private methods\n\n function getRequiredAffixClass(unpin, position, elementHeight) {\n\n var scrollTop = getScrollTop();\n var scrollHeight = getScrollHeight();\n\n if(scrollTop <= offsetTop) {\n return 'top';\n } else if(unpin !== null && (scrollTop + unpin <= position.top)) {\n return 'middle';\n } else if(offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n return 'bottom';\n } else {\n return 'middle';\n }\n\n }\n\n function getScrollTop() {\n return targetEl[0] === $window ? $window.pageYOffset : targetEl[0].scrollTop;\n }\n\n function getScrollHeight() {\n return targetEl[0] === $window ? $window.document.body.scrollHeight : targetEl[0].scrollHeight;\n }\n\n $affix.init();\n return $affix;\n\n }\n\n return AffixFactory;\n\n };\n\n })\n\n .directive('bsAffix', function($affix, $window) {\n\n return {\n restrict: 'EAC',\n require: '^?bsAffixTarget',\n link: function postLink(scope, element, attr, affixTarget) {\n\n var options = {scope: scope, target: affixTarget ? affixTarget.$element : angular.element($window)};\n angular.forEach(['offsetTop', 'offsetBottom', 'offsetParent', 'offsetUnpin', 'inlineStyles'], function(key) {\n if(angular.isDefined(attr[key])) {\n var option = attr[key];\n if (/true/i.test(option)) option = true;\n if (/false/i.test(option)) option = false;\n options[key] = option;\n }\n });\n\n var affix = $affix(element, options);\n scope.$on('$destroy', function() {\n affix && affix.destroy();\n options = null;\n affix = null;\n });\n\n }\n };\n\n })\n\n .directive('bsAffixTarget', function() {\n return {\n controller: function($element) {\n this.$element = $element;\n }\n };\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.button', [])\n\n .provider('$button', function() {\n\n var defaults = this.defaults = {\n activeClass:'active',\n toggleEvent:'click'\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsCheckboxGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"checkbox\"]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.attr('bs-checkbox', '');\n childEl.attr('ng-model', attr.ngModel + '.' + childEl.attr('value'));\n });\n }\n\n };\n\n })\n\n .directive('bsCheckbox', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support label > input[type=\"checkbox\"]\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var trueValue = angular.isDefined(attr.trueValue) ? attr.trueValue : true;\n if(constantValueRegExp.test(attr.trueValue)) {\n trueValue = scope.$eval(attr.trueValue);\n }\n var falseValue = angular.isDefined(attr.falseValue) ? attr.falseValue : false;\n if(constantValueRegExp.test(attr.falseValue)) {\n falseValue = scope.$eval(attr.falseValue);\n }\n\n // Parse exotic values\n var hasExoticValues = typeof trueValue !== 'boolean' || typeof falseValue !== 'boolean';\n if(hasExoticValues) {\n controller.$parsers.push(function(viewValue) {\n // console.warn('$parser', element.attr('ng-model'), 'viewValue', viewValue);\n return viewValue ? trueValue : falseValue;\n });\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n return angular.equals(modelValue, trueValue);\n });\n // Fix rendering for exotic values\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n controller.$render();\n });\n }\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, trueValue);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('ng-model'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n if(!isInput) {\n controller.$setViewValue(!activeElement.hasClass('active'));\n }\n if(!hasExoticValues) {\n controller.$render();\n }\n });\n });\n\n }\n\n };\n\n })\n\n .directive('bsRadioGroup', function() {\n\n return {\n restrict: 'A',\n require: 'ngModel',\n compile: function postLink(element, attr) {\n element.attr('data-toggle', 'buttons');\n element.removeAttr('ng-model');\n var children = element[0].querySelectorAll('input[type=\"radio\"]');\n angular.forEach(children, function(child) {\n angular.element(child).attr('bs-radio', '');\n angular.element(child).attr('ng-model', attr.ngModel);\n });\n }\n\n };\n\n })\n\n .directive('bsRadio', function($button, $$rAF) {\n\n var defaults = $button.defaults;\n var constantValueRegExp = /^(true|false|\\d+)$/;\n\n return {\n restrict: 'A',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n var options = defaults;\n\n // Support `label > input[type=\"radio\"]` markup\n var isInput = element[0].nodeName === 'INPUT';\n var activeElement = isInput ? element.parent() : element;\n\n var value;\n attr.$observe('value', function(v) {\n value = constantValueRegExp.test(v) ? scope.$eval(v) : v;\n controller.$render();\n });\n\n // model -> view\n controller.$render = function () {\n // console.warn('$render', element.attr('value'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var isActive = angular.equals(controller.$modelValue, value);\n $$rAF(function() {\n if(isInput) element[0].checked = isActive;\n activeElement.toggleClass(options.activeClass, isActive);\n });\n };\n\n // view -> model\n element.bind(options.toggleEvent, function() {\n scope.$apply(function () {\n // console.warn('!click', element.attr('value'), 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue, 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue);\n controller.$setViewValue(value);\n controller.$render();\n });\n });\n\n }\n\n };\n\n });\n","'use strict';\n\n// @BUG: following snippet won't compile correctly\n// @TODO: submit issue to core\n// ' ' +\n\nangular.module('mgcrea.ngStrap.alert', ['mgcrea.ngStrap.modal'])\n\n .provider('$alert', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'alert',\n prefixEvent: 'alert',\n placement: null,\n template: 'alert/alert.tpl.html',\n container: false,\n element: null,\n backdrop: false,\n keyboard: true,\n show: true,\n // Specific options\n duration: false,\n type: false,\n dismissable: true\n };\n\n this.$get = function($modal, $timeout) {\n\n function AlertFactory(config) {\n\n var $alert = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $alert = $modal(options);\n\n // Support scope as string options [/*title, content, */ type, dismissable]\n $alert.$scope.dismissable = !!options.dismissable;\n if(options.type) {\n $alert.$scope.type = options.type;\n }\n\n // Support auto-close duration\n var show = $alert.show;\n if(options.duration) {\n $alert.show = function() {\n show();\n $timeout(function() {\n $alert.hide();\n }, options.duration * 1000);\n };\n }\n\n return $alert;\n\n }\n\n return AlertFactory;\n\n };\n\n })\n\n .directive('bsAlert', function($window, $sce, $alert) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'placement', 'keyboard', 'html', 'container', 'animation', 'duration', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['keyboard', 'html', 'container', 'dismissable'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content', 'type'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAlert && scope.$watch(attr.bsAlert, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize alert\n var alert = $alert(options);\n\n // Trigger\n element.on(attr.trigger || 'click', alert.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (alert) alert.destroy();\n options = null;\n alert = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.aside', ['mgcrea.ngStrap.modal'])\n\n .provider('$aside', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade-and-slide-right',\n prefixClass: 'aside',\n prefixEvent: 'aside',\n placement: 'right',\n template: 'aside/aside.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($modal) {\n\n function AsideFactory(config) {\n\n var $aside = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $aside = $modal(options);\n\n return $aside;\n\n }\n\n return AsideFactory;\n\n };\n\n })\n\n .directive('bsAside', function($window, $sce, $aside) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsAside && scope.$watch(attr.bsAside, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize aside\n var aside = $aside(options);\n\n // Trigger\n element.on(attr.trigger || 'click', aside.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (aside) aside.destroy();\n options = null;\n aside = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.collapse', [])\n\n .provider('$collapse', function() {\n\n var defaults = this.defaults = {\n animation: 'am-collapse',\n disallowToggle: false,\n activeClass: 'in',\n startCollapsed: false,\n allowMultiple: false\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['disallowToggle', 'startCollapsed', 'allowMultiple'], function(key) {\n if(angular.isDefined($attrs[key]) && falseValueRegExp.test($attrs[key]))\n self.$options[key] = false;\n });\n\n self.$toggles = [];\n self.$targets = [];\n\n self.$viewChangeListeners = [];\n\n self.$registerToggle = function(element) {\n self.$toggles.push(element);\n };\n self.$registerTarget = function(element) {\n self.$targets.push(element);\n };\n\n self.$unregisterToggle = function(element) {\n var index = self.$toggles.indexOf(element);\n // remove toggle from $toggles array\n self.$toggles.splice(index, 1);\n };\n self.$unregisterTarget = function(element) {\n var index = self.$targets.indexOf(element);\n\n // remove element from $targets array\n self.$targets.splice(index, 1);\n\n if (self.$options.allowMultiple) {\n // remove target index from $active array values\n deactivateItem(element);\n }\n\n // fix active item indexes\n fixActiveItemIndexes(index);\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n // use array to store all the currently open panels\n self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n self.$setActive = $scope.$setActive = function(value) {\n if(angular.isArray(value)) {\n self.$targets.$active = value;\n }\n else if(!self.$options.disallowToggle) {\n // toogle element active status\n isActive(value) ? deactivateItem(value) : activateItem(value);\n } else {\n activateItem(value);\n }\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$activeIndexes = function() {\n return self.$options.allowMultiple ? self.$targets.$active :\n self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n };\n\n function fixActiveItemIndexes(index) {\n // item with index was removed, so we\n // need to adjust other items index values\n var activeIndexes = self.$targets.$active;\n for(var i = 0; i < activeIndexes.length; i++) {\n if (index < activeIndexes[i]) {\n activeIndexes[i] = activeIndexes[i] - 1;\n }\n\n // the last item is active, so we need to\n // adjust its index\n if (activeIndexes[i] === self.$targets.length) {\n activeIndexes[i] = self.$targets.length - 1;\n }\n }\n }\n\n function isActive(value) {\n var activeItems = self.$targets.$active;\n return activeItems.indexOf(value) === -1 ? false : true;\n }\n\n function deactivateItem(value) {\n var index = self.$targets.$active.indexOf(value);\n if (index !== -1) {\n self.$targets.$active.splice(index, 1);\n }\n }\n\n function activateItem(value) {\n if (!self.$options.allowMultiple) {\n // remove current selected item\n self.$targets.$active.splice(0, 1);\n }\n\n if (self.$targets.$active.indexOf(value) === -1) {\n self.$targets.$active.push(value);\n }\n }\n\n };\n\n this.$get = function() {\n var $collapse = {};\n $collapse.defaults = defaults;\n $collapse.controller = controller;\n return $collapse;\n };\n\n })\n\n .directive('bsCollapse', function($window, $animate, $collapse) {\n\n var defaults = $collapse.defaults;\n\n return {\n require: ['?ngModel', 'bsCollapse'],\n controller: ['$scope', '$element', '$attrs', $collapse.controller],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n if (angular.isArray(modelValue)) {\n // model value is an array, so just replace\n // the active items directly\n bsCollapseCtrl.$setActive(modelValue);\n }\n else {\n var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n if (angular.isArray(activeIndexes)) {\n // we have an array of selected indexes\n if (activeIndexes.indexOf(modelValue * 1) === -1) {\n // item with modelValue index is not active\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n else if (activeIndexes !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n return modelValue;\n });\n\n }\n\n }\n };\n\n })\n\n .directive('bsCollapseToggle', function() {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base attr\n element.attr('data-toggle', 'collapse');\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerToggle(element);\n\n // remove toggle from collapse controller when toggle is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterToggle(element);\n });\n\n element.on('click', function() {\n var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n bsCollapseCtrl.$setActive(index * 1);\n scope.$apply();\n });\n\n }\n };\n\n })\n\n .directive('bsCollapseTarget', function($animate) {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n // scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base class\n element.addClass('collapse');\n\n // Add animation class\n if(bsCollapseCtrl.$options.animation) {\n element.addClass(bsCollapseCtrl.$options.animation);\n }\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerTarget(element);\n\n // remove pane target from collapse controller when target is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterTarget(element);\n });\n\n function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$activeIndexes();\n var action = 'removeClass';\n if (angular.isArray(active)) {\n if (active.indexOf(index) !== -1) {\n action = 'addClass';\n }\n }\n else if (index === active) {\n action = 'addClass';\n }\n\n $animate[action](element, bsCollapseCtrl.$options.activeClass);\n }\n\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.datepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$datepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'datepicker',\n prefixClass: 'datepicker',\n placement: 'bottom-left',\n template: 'datepicker/datepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: false,\n dateType: 'date',\n dateFormat: 'shortDate',\n timezone: null,\n modelDateFormat: null,\n dayFormat: 'dd',\n monthFormat: 'MMM',\n yearFormat: 'yyyy',\n monthTitleFormat: 'MMMM yyyy',\n yearTitleFormat: 'yyyy',\n strictFormat: false,\n autoclose: false,\n minDate: -Infinity,\n maxDate: +Infinity,\n startView: 0,\n minView: 0,\n startWeek: 0,\n daysOfWeekDisabled: '',\n iconLeft: 'glyphicon glyphicon-chevron-left',\n iconRight: 'glyphicon glyphicon-chevron-right'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, datepickerViews, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function DatepickerFactory(element, controller, config) {\n\n var $datepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $datepicker.$options;\n var scope = $datepicker.$scope;\n if(options.startView) options.startView -= options.minView;\n\n // View vars\n\n var pickerViews = datepickerViews($datepicker);\n $datepicker.$views = pickerViews.views;\n var viewDate = pickerViews.viewDate;\n scope.$mode = options.startView;\n scope.$iconLeft = options.iconLeft;\n scope.$iconRight = options.iconRight;\n var $picker = $datepicker.$views[scope.$mode];\n\n // Scope methods\n\n scope.$select = function(date) {\n $datepicker.select(date);\n };\n scope.$selectPane = function(value) {\n $datepicker.$selectPane(value);\n };\n scope.$toggleMode = function() {\n $datepicker.setMode((scope.$mode + 1) % $datepicker.$views.length);\n };\n\n // Public methods\n\n $datepicker.update = function(date) {\n // console.warn('$datepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $datepicker.$date = date;\n $picker.update.call($picker, date);\n }\n // Build only if pristine\n $datepicker.$build(true);\n };\n\n $datepicker.updateDisabledDates = function(dateRanges) {\n options.disabledDateRanges = dateRanges;\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], $datepicker.$setDisabledEl);\n }\n };\n\n $datepicker.select = function(date, keep) {\n // console.warn('$datepicker.select', date, scope.$mode);\n if(!angular.isDate(controller.$dateValue)) controller.$dateValue = new Date(date);\n if(!scope.$mode || keep) {\n controller.$setViewValue(angular.copy(date));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $datepicker.hide(true); });\n }\n } else {\n angular.extend(viewDate, {year: date.getFullYear(), month: date.getMonth(), date: date.getDate()});\n $datepicker.setMode(scope.$mode - 1);\n $datepicker.$build();\n }\n };\n\n $datepicker.setMode = function(mode) {\n // console.warn('$datepicker.setMode', mode);\n scope.$mode = mode;\n $picker = $datepicker.$views[scope.$mode];\n $datepicker.$build();\n };\n\n // Protected methods\n\n $datepicker.$build = function(pristine) {\n // console.warn('$datepicker.$build() viewDate=%o', viewDate);\n if(pristine === true && $picker.built) return;\n if(pristine === false && !$picker.built) return;\n $picker.build.call($picker);\n };\n\n $datepicker.$updateSelected = function() {\n for(var i = 0, l = scope.rows.length; i < l; i++) {\n angular.forEach(scope.rows[i], updateSelected);\n }\n };\n\n $datepicker.$isSelected = function(date) {\n return $picker.isSelected(date);\n };\n\n $datepicker.$setDisabledEl = function(el) {\n el.disabled = $picker.isDisabled(el.date);\n };\n\n $datepicker.$selectPane = function(value) {\n var steps = $picker.steps;\n // set targetDate to first day of month to avoid problems with\n // date values rollover. This assumes the viewDate does not\n // depend on the day of the month\n var targetDate = new Date(Date.UTC(viewDate.year + ((steps.year || 0) * value), viewDate.month + ((steps.month || 0) * value), 1));\n angular.extend(viewDate, {year: targetDate.getUTCFullYear(), month: targetDate.getUTCMonth(), date: targetDate.getUTCDate()});\n $datepicker.$build();\n };\n\n $datepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $datepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n if(evt.keyCode === 13) {\n if(!scope.$mode) {\n return $datepicker.hide(true);\n } else {\n return scope.$apply(function() { $datepicker.setMode(scope.$mode - 1); });\n }\n }\n\n // Navigate with keyboard\n $picker.onKeyDown(evt);\n parentScope.$digest();\n };\n\n // Private\n\n function updateSelected(el) {\n el.selected = $datepicker.$isSelected(el.date);\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $datepicker.init;\n $datepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'date');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $datepicker.destroy;\n $datepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $datepicker.show;\n $datepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // if $datepicker is no longer showing, don't setup events\n if(!$datepicker.$isShown) return;\n $datepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $datepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $datepicker.hide;\n $datepicker.hide = function(blur) {\n if(!$datepicker.$isShown) return;\n $datepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $datepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $datepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $datepicker;\n\n }\n\n DatepickerFactory.defaults = defaults;\n return DatepickerFactory;\n\n };\n\n })\n\n .directive('bsDatepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $datepicker) {\n\n var defaults = $datepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'html', 'animation', 'template', 'autoclose', 'dateType', 'dateFormat', 'timezone', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!datepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(datepicker),?/i);\n newValue === true ? datepicker.show() : datepicker.hide();\n });\n\n // Initialize datepicker\n var datepicker = $datepicker(element, controller, options);\n options = datepicker.$options;\n // Set expected iOS format\n if(isNative && options.useNative) options.dateFormat = 'yyyy-MM-dd';\n\n var lang = options.lang;\n\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n // Observe attributes for changes\n angular.forEach(['minDate', 'maxDate'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n // console.warn('attr.$observe(%s)=%o', key, newValue);\n datepicker.$options[key] = dateParser.getDateForAttribute(key, newValue);\n // Build only if dirty\n !isNaN(datepicker.$options[key]) && datepicker.$build(false);\n validateAgainstMinMaxDate(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n datepicker.update(controller.$dateValue);\n }, true);\n\n // Normalize undefined/null/empty array,\n // so that we don't treat changing from undefined->null as a change.\n function normalizeDateRanges(ranges) {\n if (!ranges || !ranges.length) return null;\n return ranges;\n }\n\n if (angular.isDefined(attr.disabledDates)) {\n scope.$watch(attr.disabledDates, function(disabledRanges, previousValue) {\n disabledRanges = normalizeDateRanges(disabledRanges);\n previousValue = normalizeDateRanges(previousValue);\n\n if (disabledRanges) {\n datepicker.updateDisabledDates(disabledRanges);\n }\n });\n }\n\n function validateAgainstMinMaxDate(parsedDate) {\n if (!angular.isDate(parsedDate)) return;\n var isMinValid = isNaN(datepicker.$options.minDate) || parsedDate.getTime() >= datepicker.$options.minDate;\n var isMaxValid = isNaN(datepicker.$options.maxDate) || parsedDate.getTime() <= datepicker.$options.maxDate;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(isValid) controller.$dateValue = parsedDate;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n controller.$setValidity('date', true);\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n return null;\n }\n var parsedDate = dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedDate || isNaN(parsedDate.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxDate(parsedDate);\n }\n\n if(options.dateType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedDate, options.timezone, true);\n return formatDate(date, options.modelDateFormat || options.dateFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.dateType === 'number') {\n return date.getTime();\n } else if(options.dateType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.dateType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.dateType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelDateFormat);\n } else if(options.dateType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) {\n // var today = new Date();\n // date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n // }\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getDateFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getDateFormattedString());\n };\n\n function getDateFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(datepicker) datepicker.destroy();\n options = null;\n datepicker = null;\n });\n\n }\n };\n\n })\n\n .provider('datepickerViews', function() {\n\n var defaults = this.defaults = {\n dayFormat: 'dd',\n daySplit: 7\n };\n\n // Split array into smaller arrays\n function split(arr, size) {\n var arrays = [];\n while(arr.length > 0) {\n arrays.push(arr.splice(0, size));\n }\n return arrays;\n }\n\n // Modulus operator\n function mod(n, m) {\n return ((n % m) + m) % m;\n }\n\n this.$get = function($dateFormatter, $dateParser, $sce) {\n\n return function(picker) {\n\n var scope = picker.$scope;\n var options = picker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format) {\n return $dateFormatter.formatDate(date, format, lang);\n };\n var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n var weekDaysLabelsHtml = $sce.trustAsHtml('' + weekDaysLabels.join('') + '');\n\n var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n\n var views = [{\n format: options.dayFormat,\n split: 7,\n steps: { month: 1 },\n update: function(date, force) {\n if(!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getDate() !== viewDate.date || date.getDate() === 1) {\n // chaging picker current month will cause viewDate.date to be set to first day of the month,\n // in $datepicker.$selectPane, so picker would not update selected day display if\n // user picks first day of the new month.\n // As a workaround, we are always forcing update when picked date is first day of month.\n viewDate.date = picker.$date.getDate();\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1), firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5), firstDateOffset = firstDate.getTimezoneOffset();\n var today = dateParser.timezoneOffsetAdjust(new Date(), options.timezone).toDateString();\n // Handle daylight time switch\n if(firstDateOffset !== firstDayOfMonthOffset) firstDate = new Date(+firstDate + (firstDateOffset - firstDayOfMonthOffset) * 60e3);\n var days = [], day;\n for(var i = 0; i < 42; i++) { // < 7 * 6\n day = dateParser.daylightSavingAdjust(new Date(firstDate.getFullYear(), firstDate.getMonth(), firstDate.getDate() + i));\n days.push({date: day, isToday: day.toDateString() === today, label: formatDate(day, this.format), selected: picker.$date && this.isSelected(day), muted: day.getMonth() !== viewDate.month, disabled: this.isDisabled(day)});\n }\n scope.title = formatDate(firstDayOfMonth, options.monthTitleFormat);\n scope.showLabels = true;\n scope.labels = weekDaysLabelsHtml;\n scope.rows = split(days, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth() && date.getDate() === picker.$date.getDate();\n },\n isDisabled: function(date) {\n var time = date.getTime();\n\n // Disabled because of min/max date.\n if (time < options.minDate || time > options.maxDate) return true;\n\n // Disabled due to being a disabled day of the week\n if (options.daysOfWeekDisabled.indexOf(date.getDay()) !== -1) return true;\n\n // Disabled because of disabled date range.\n if (options.disabledDateRanges) {\n for (var i = 0; i < options.disabledDateRanges.length; i++) {\n if (time >= options.disabledDateRanges[i].start && time <= options.disabledDateRanges[i].end) {\n return true;\n }\n }\n }\n\n return false;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualTime = picker.$date.getTime();\n var newDate;\n\n if(evt.keyCode === 37) newDate = new Date(actualTime - 1 * 864e5);\n else if(evt.keyCode === 38) newDate = new Date(actualTime - 7 * 864e5);\n else if(evt.keyCode === 39) newDate = new Date(actualTime + 1 * 864e5);\n else if(evt.keyCode === 40) newDate = new Date(actualTime + 7 * 864e5);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'month',\n format: options.monthFormat,\n split: 4,\n steps: { year: 1 },\n update: function(date, force) {\n if(!this.built || date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getMonth() !== viewDate.month) {\n angular.extend(viewDate, {month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstMonth = new Date(viewDate.year, 0, 1);\n var months = [], month;\n for (var i = 0; i < 12; i++) {\n month = new Date(viewDate.year, i, 1);\n months.push({date: month, label: formatDate(month, this.format), selected: picker.$isSelected(month), disabled: this.isDisabled(month)});\n }\n scope.title = formatDate(month, options.yearTitleFormat);\n scope.showLabels = false;\n scope.rows = split(months, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear() && date.getMonth() === picker.$date.getMonth();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear(), date.getMonth() + 1, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualMonth = picker.$date.getMonth();\n var newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setMonth(actualMonth - 1);\n else if(evt.keyCode === 38) newDate.setMonth(actualMonth - 4);\n else if(evt.keyCode === 39) newDate.setMonth(actualMonth + 1);\n else if(evt.keyCode === 40) newDate.setMonth(actualMonth + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }, {\n name: 'year',\n format: options.yearFormat,\n split: 4,\n steps: { year: 12 },\n update: function(date, force) {\n if(!this.built || force || parseInt(date.getFullYear()/20, 10) !== parseInt(viewDate.year/20, 10)) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$build();\n } else if(date.getFullYear() !== viewDate.year) {\n angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n picker.$updateSelected();\n }\n },\n build: function() {\n var firstYear = viewDate.year - viewDate.year % (this.split * 3);\n var years = [], year;\n for (var i = 0; i < 12; i++) {\n year = new Date(firstYear + i, 0, 1);\n years.push({date: year, label: formatDate(year, this.format), selected: picker.$isSelected(year), disabled: this.isDisabled(year)});\n }\n scope.title = years[0].label + '-' + years[years.length - 1].label;\n scope.showLabels = false;\n scope.rows = split(years, this.split);\n this.built = true;\n },\n isSelected: function(date) {\n return picker.$date && date.getFullYear() === picker.$date.getFullYear();\n },\n isDisabled: function(date) {\n var lastDate = +new Date(date.getFullYear() + 1, 0, 0);\n return lastDate < options.minDate || date.getTime() > options.maxDate;\n },\n onKeyDown: function(evt) {\n if (!picker.$date) {\n return;\n }\n var actualYear = picker.$date.getFullYear(),\n newDate = new Date(picker.$date);\n\n if(evt.keyCode === 37) newDate.setYear(actualYear - 1);\n else if(evt.keyCode === 38) newDate.setYear(actualYear - 4);\n else if(evt.keyCode === 39) newDate.setYear(actualYear + 1);\n else if(evt.keyCode === 40) newDate.setYear(actualYear + 4);\n\n if (!this.isDisabled(newDate)) picker.select(newDate, true);\n }\n }];\n\n return {\n views: options.minView ? Array.prototype.slice.call(views, options.minView) : views,\n viewDate: viewDate\n };\n\n };\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.dropdown', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$dropdown', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'dropdown',\n prefixEvent: 'dropdown',\n placement: 'bottom-left',\n template: 'dropdown/dropdown.tpl.html',\n trigger: 'click',\n container: false,\n keyboard: true,\n html: false,\n delay: 0\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var matchesSelector = Element.prototype.matchesSelector || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector;\n\n function DropdownFactory(element, config) {\n\n var $dropdown = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n var scope = $dropdown.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n $dropdown = $tooltip(element, options);\n var parentEl = element.parent();\n\n // Protected methods\n\n $dropdown.$onKeyDown = function(evt) {\n if (!/(38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Retrieve focused index\n var items = angular.element($dropdown.$element[0].querySelectorAll('li:not(.divider) a'));\n if(!items.length) return;\n var index;\n angular.forEach(items, function(el, i) {\n if(matchesSelector && matchesSelector.call(el, ':focus')) index = i;\n });\n\n // Navigate with keyboard\n if(evt.keyCode === 38 && index > 0) index--;\n else if(evt.keyCode === 40 && index < items.length - 1) index++;\n else if(angular.isUndefined(index)) index = 0;\n items.eq(index)[0].focus();\n\n };\n\n // Overrides\n\n var show = $dropdown.show;\n $dropdown.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n options.keyboard && $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n bodyEl.on('click', onBodyClick);\n }, 0, false);\n parentEl.hasClass('dropdown') && parentEl.addClass('open');\n };\n\n var hide = $dropdown.hide;\n $dropdown.hide = function() {\n if(!$dropdown.$isShown) return;\n options.keyboard && $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n bodyEl.off('click', onBodyClick);\n parentEl.hasClass('dropdown') && parentEl.removeClass('open');\n hide();\n };\n\n var destroy = $dropdown.destroy;\n $dropdown.destroy = function() {\n bodyEl.off('click', onBodyClick);\n destroy();\n };\n\n // Private functions\n\n function onBodyClick(evt) {\n if(evt.target === element[0]) return;\n return evt.target !== element[0] && $dropdown.hide();\n }\n\n return $dropdown;\n\n }\n\n return DropdownFactory;\n\n };\n\n })\n\n .directive('bsDropdown', function($window, $sce, $dropdown) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as an object\n attr.bsDropdown && scope.$watch(attr.bsDropdown, function(newValue, oldValue) {\n scope.content = newValue;\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!dropdown || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(dropdown),?/i);\n newValue === true ? dropdown.show() : dropdown.hide();\n });\n\n // Initialize dropdown\n var dropdown = $dropdown(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (dropdown) dropdown.destroy();\n options = null;\n dropdown = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dateFormatter', [])\n\n .service('$dateFormatter', function($locale, dateFilter) {\n\n // The unused `lang` arguments are on purpose. The default implementation does not\n // use them and it always uses the locale loaded into the `$locale` service.\n // Custom implementations might use it, thus allowing different directives to\n // have different languages.\n\n this.getDefaultLocale = function() {\n return $locale.id;\n };\n\n // Format is either a data format name, e.g. \"shortTime\" or \"fullDate\", or a date format\n // Return either the corresponding date format or the given date format.\n this.getDatetimeFormat = function(format, lang) {\n return $locale.DATETIME_FORMATS[format] || format;\n };\n\n this.weekdaysShort = function(lang) {\n return $locale.DATETIME_FORMATS.SHORTDAY;\n };\n\n function splitTimeFormat(format) {\n return /(h+)([:\\.])?(m+)([:\\.])?(s*)[ ]?(a?)/i.exec(format).slice(1);\n }\n\n // h:mm a => h\n this.hoursFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[0];\n };\n\n // h:mm a => mm\n this.minutesFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[2];\n };\n\n // h:mm:ss a => ss\n this.secondsFormat = function(timeFormat) {\n return splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => :\n this.timeSeparator = function(timeFormat) {\n return splitTimeFormat(timeFormat)[1];\n };\n\n // h:mm:ss a => true, h:mm a => false\n this.showSeconds = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[4];\n };\n\n // h:mm a => true, H.mm => false\n this.showAM = function(timeFormat) {\n return !!splitTimeFormat(timeFormat)[5];\n };\n\n this.formatDate = function(date, format, lang, timezone){\n return dateFilter(date, format, timezone);\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dateParser', [])\n\n.provider('$dateParser', function($localeProvider) {\n\n // define a custom ParseDate object to use instead of native Date\n // to avoid date values wrapping when setting date component values\n function ParseDate() {\n this.year = 1970;\n this.month = 0;\n this.day = 1;\n this.hours = 0;\n this.minutes = 0;\n this.seconds = 0;\n this.milliseconds = 0;\n }\n\n ParseDate.prototype.setMilliseconds = function(value) { this.milliseconds = value; };\n ParseDate.prototype.setSeconds = function(value) { this.seconds = value; };\n ParseDate.prototype.setMinutes = function(value) { this.minutes = value; };\n ParseDate.prototype.setHours = function(value) { this.hours = value; };\n ParseDate.prototype.getHours = function() { return this.hours; };\n ParseDate.prototype.setDate = function(value) { this.day = value; };\n ParseDate.prototype.setMonth = function(value) { this.month = value; };\n ParseDate.prototype.setFullYear = function(value) { this.year = value; };\n ParseDate.prototype.fromDate = function(value) {\n this.year = value.getFullYear();\n this.month = value.getMonth();\n this.day = value.getDate();\n this.hours = value.getHours();\n this.minutes = value.getMinutes();\n this.seconds = value.getSeconds();\n this.milliseconds = value.getMilliseconds();\n return this;\n };\n\n ParseDate.prototype.toDate = function() {\n return new Date(this.year, this.month, this.day, this.hours, this.minutes, this.seconds, this.milliseconds);\n };\n\n var proto = ParseDate.prototype;\n\n function noop() {\n }\n\n function isNumeric(n) {\n return !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n function indexOfCaseInsensitive(array, value) {\n var len = array.length, str=value.toString().toLowerCase();\n for (var i=0; i 12 when midnight changeover, but then cannot generate\n * midnight datetime, so jump to 1AM, otherwise reset.\n * @param date (Date) the date to check\n * @return (Date) the corrected date\n *\n * __ copied from jquery ui datepicker __\n */\n $dateParser.daylightSavingAdjust = function(date) {\n if (!date) {\n return null;\n }\n date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n return date;\n };\n\n /* Correct the date for timezone offset.\n * @param date (Date) the date to adjust\n * @param timezone (string) the timezone to adjust for\n * @param undo (boolean) to add or subtract timezone offset\n * @return (Date) the corrected date\n */\n $dateParser.timezoneOffsetAdjust = function(date, timezone, undo) {\n if (!date) {\n return null;\n }\n // Right now, only 'UTC' is supported.\n if (timezone && timezone === 'UTC') {\n date = new Date(date.getTime());\n date.setMinutes(date.getMinutes() + (undo?-1:1)*date.getTimezoneOffset());\n }\n return date;\n };\n\n // Private functions\n\n function setMapForFormat(format) {\n var keys = Object.keys(setFnMap), i;\n var map = [], sortedMap = [];\n // Map to setFn\n var clonedFormat = format;\n for(i = 0; i < keys.length; i++) {\n if(format.split(keys[i]).length > 1) {\n var index = clonedFormat.search(keys[i]);\n format = format.split(keys[i]).join('');\n if(setFnMap[keys[i]]) {\n map[index] = setFnMap[keys[i]];\n }\n }\n }\n // Sort result map\n angular.forEach(map, function(v) {\n // conditional required since angular.forEach broke around v1.2.21\n // related pr: https://github.com/angular/angular.js/pull/8525\n if(v) sortedMap.push(v);\n });\n return sortedMap;\n }\n\n function escapeReservedSymbols(text) {\n return text.replace(/\\//g, '[\\\\/]').replace('/-/g', '[-]').replace(/\\./g, '[.]').replace(/\\\\s/g, '[\\\\s]');\n }\n\n function regExpForFormat(format) {\n var keys = Object.keys(regExpMap), i;\n\n var re = format;\n // Abstract replaces to avoid collisions\n for(i = 0; i < keys.length; i++) {\n re = re.split(keys[i]).join('${' + i + '}');\n }\n // Replace abstracted values\n for(i = 0; i < keys.length; i++) {\n re = re.split('${' + i + '}').join('(' + regExpMap[keys[i]] + ')');\n }\n format = escapeReservedSymbols(format);\n\n return new RegExp('^' + re + '$', ['i']);\n }\n\n $dateParser.init();\n return $dateParser;\n\n };\n\n return DateParserFactory;\n\n };\n\n});\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.debounce', [])\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L693\n.factory('debounce', function($timeout) {\n return function(func, wait, immediate) {\n var timeout = null;\n return function() {\n var context = this,\n args = arguments,\n callNow = immediate && !timeout;\n if(timeout) {\n $timeout.cancel(timeout);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(!immediate) {\n func.apply(context, args);\n }\n }, wait, false);\n if(callNow) {\n func.apply(context, args);\n }\n return timeout;\n };\n };\n})\n\n\n// @source jashkenas/underscore\n// @url https://github.com/jashkenas/underscore/blob/1.5.2/underscore.js#L661\n.factory('throttle', function($timeout) {\n return function(func, wait, options) {\n var timeout = null;\n options || (options = {});\n return function() {\n var context = this,\n args = arguments;\n if(!timeout) {\n if(options.leading !== false) {\n func.apply(context, args);\n }\n timeout = $timeout(function later() {\n timeout = null;\n if(options.trailing !== false) {\n func.apply(context, args);\n }\n }, wait, false);\n }\n };\n };\n});\n\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n .factory('dimensions', function($document, $window) {\n\n var jqLite = angular.element;\n var fn = {};\n\n /**\n * Test the element nodeName\n * @param element\n * @param name\n */\n var nodeName = fn.nodeName = function(element, name) {\n return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();\n };\n\n /**\n * Returns the element computed style\n * @param element\n * @param prop\n * @param extra\n */\n fn.css = function(element, prop, extra) {\n var value;\n if (element.currentStyle) { //IE\n value = element.currentStyle[prop];\n } else if (window.getComputedStyle) {\n value = window.getComputedStyle(element)[prop];\n } else {\n value = element.style[prop];\n }\n return extra === true ? parseFloat(value) || 0 : value;\n };\n\n /**\n * Provides read-only equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.offset = function(element) {\n var boxRect = element.getBoundingClientRect();\n var docElement = element.ownerDocument;\n return {\n width: boxRect.width || element.offsetWidth,\n height: boxRect.height || element.offsetHeight,\n top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),\n left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)\n };\n };\n \n /**\n * Provides set equivalent of jQuery's offset function:\n * @required-by bootstrap-tooltip\n * @url http://api.jquery.com/offset/\n * @param element\n * @param options\n * @param i\n */\n fn.setOffset = function (element, options, i) {\n var curPosition,\n curLeft,\n curCSSTop,\n curTop,\n curOffset,\n curCSSLeft,\n calculatePosition,\n position = fn.css(element, 'position'),\n curElem = angular.element(element),\n props = {};\n \n // Set position first, in-case top/left are set even on static elem\n if (position === 'static') {\n element.style.position = 'relative';\n }\n \n curOffset = fn.offset(element);\n curCSSTop = fn.css(element, 'top');\n curCSSLeft = fn.css(element, 'left');\n calculatePosition = (position === 'absolute' || position === 'fixed') && \n (curCSSTop + curCSSLeft).indexOf('auto') > -1;\n \n // Need to be able to calculate position if either\n // top or left is auto and position is either absolute or fixed\n if (calculatePosition) {\n curPosition = fn.position(element);\n curTop = curPosition.top;\n curLeft = curPosition.left;\n } else {\n curTop = parseFloat(curCSSTop) || 0;\n curLeft = parseFloat(curCSSLeft) || 0;\n }\n \n if (angular.isFunction(options)) {\n options = options.call(element, i, curOffset);\n }\n \n if (options.top !== null ) {\n props.top = (options.top - curOffset.top) + curTop;\n }\n if ( options.left !== null ) {\n props.left = (options.left - curOffset.left) + curLeft;\n }\n\n if ('using' in options) {\n options.using.call(curElem, props);\n } else {\n curElem.css({\n top: props.top + 'px',\n left: props.left + 'px'\n });\n }\n };\n\n /**\n * Provides read-only equivalent of jQuery's position function\n * @required-by bootstrap-tooltip, bootstrap-affix\n * @url http://api.jquery.com/offset/\n * @param element\n */\n fn.position = function(element) {\n\n var offsetParentRect = {top: 0, left: 0},\n offsetParentElement,\n offset;\n\n // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n if (fn.css(element, 'position') === 'fixed') {\n\n // We assume that getBoundingClientRect is available when computed position is fixed\n offset = element.getBoundingClientRect();\n\n } else {\n\n // Get *real* offsetParentElement\n offsetParentElement = offsetParent(element);\n\n // Get correct offsets\n offset = fn.offset(element);\n if (!nodeName(offsetParentElement, 'html')) {\n offsetParentRect = fn.offset(offsetParentElement);\n }\n\n // Add offsetParent borders\n offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);\n offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);\n }\n\n // Subtract parent offsets and element margins\n return {\n width: element.offsetWidth,\n height: element.offsetHeight,\n top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),\n left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)\n };\n\n };\n\n /**\n * Returns the closest, non-statically positioned offsetParent of a given element\n * @required-by fn.position\n * @param element\n */\n var offsetParent = function offsetParentElement(element) {\n var docElement = element.ownerDocument;\n var offsetParent = element.offsetParent || docElement;\n if(nodeName(offsetParent, '#document')) return docElement.documentElement;\n while(offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {\n offsetParent = offsetParent.offsetParent;\n }\n return offsetParent || docElement.documentElement;\n };\n\n /**\n * Provides equivalent of jQuery's height function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/height/\n * @param element\n * @param outer\n */\n fn.height = function(element, outer) {\n var value = element.offsetHeight;\n if(outer) {\n value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);\n } else {\n value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);\n }\n return value;\n };\n\n /**\n * Provides equivalent of jQuery's width function\n * @required-by bootstrap-affix\n * @url http://api.jquery.com/width/\n * @param element\n * @param outer\n */\n fn.width = function(element, outer) {\n var value = element.offsetWidth;\n if(outer) {\n value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);\n } else {\n value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);\n }\n return value;\n };\n\n return fn;\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.helpers.parseOptions', [])\n\n .provider('$parseOptions', function() {\n\n var defaults = this.defaults = {\n regexp: /^\\s*(.*?)(?:\\s+as\\s+(.*?))?(?:\\s+group\\s+by\\s+(.*))?\\s+for\\s+(?:([\\$\\w][\\$\\w]*)|(?:\\(\\s*([\\$\\w][\\$\\w]*)\\s*,\\s*([\\$\\w][\\$\\w]*)\\s*\\)))\\s+in\\s+(.*?)(?:\\s+track\\s+by\\s+(.*?))?$/\n };\n\n this.$get = function($parse, $q) {\n\n function ParseOptionsFactory(attr, config) {\n\n var $parseOptions = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n $parseOptions.$values = [];\n\n // Private vars\n var match, displayFn, valueName, keyName, groupByFn, valueFn, valuesFn;\n\n $parseOptions.init = function() {\n $parseOptions.$match = match = attr.match(options.regexp);\n displayFn = $parse(match[2] || match[1]),\n valueName = match[4] || match[6],\n keyName = match[5],\n groupByFn = $parse(match[3] || ''),\n valueFn = $parse(match[2] ? match[1] : valueName),\n valuesFn = $parse(match[7]);\n };\n\n $parseOptions.valuesFn = function(scope, controller) {\n return $q.when(valuesFn(scope, controller))\n .then(function(values) {\n $parseOptions.$values = values ? parseValues(values, scope) : {};\n return $parseOptions.$values;\n });\n };\n\n $parseOptions.displayValue = function(modelValue) {\n var scope = {};\n scope[valueName] = modelValue;\n return displayFn(scope);\n };\n\n // Private functions\n\n function parseValues(values, scope) {\n return values.map(function(match, index) {\n var locals = {}, label, value;\n locals[valueName] = match;\n label = displayFn(scope, locals);\n value = valueFn(scope, locals);\n return {label: label, value: value, index: index};\n });\n }\n\n $parseOptions.init();\n return $parseOptions;\n\n }\n\n return ParseOptionsFactory;\n\n };\n\n });\n","'use strict';\n\n(angular.version.minor < 3 && angular.version.dot < 14) && angular.module('ng')\n\n.factory('$$rAF', function($window, $timeout) {\n\n var requestAnimationFrame = $window.requestAnimationFrame ||\n $window.webkitRequestAnimationFrame ||\n $window.mozRequestAnimationFrame;\n\n var cancelAnimationFrame = $window.cancelAnimationFrame ||\n $window.webkitCancelAnimationFrame ||\n $window.mozCancelAnimationFrame ||\n $window.webkitCancelRequestAnimationFrame;\n\n var rafSupported = !!requestAnimationFrame;\n var raf = rafSupported ?\n function(fn) {\n var id = requestAnimationFrame(fn);\n return function() {\n cancelAnimationFrame(id);\n };\n } :\n function(fn) {\n var timer = $timeout(fn, 16.66, false); // 1000 / 60 = 16.666\n return function() {\n $timeout.cancel(timer);\n };\n };\n\n raf.supported = rafSupported;\n\n return raf;\n\n});\n\n// .factory('$$animateReflow', function($$rAF, $document) {\n\n// var bodyEl = $document[0].body;\n\n// return function(fn) {\n// //the returned function acts as the cancellation function\n// return $$rAF(function() {\n// //the line below will force the browser to perform a repaint\n// //so that all the animated elements within the animation frame\n// //will be properly updated and drawn on screen. This is\n// //required to perform multi-class CSS based animations with\n// //Firefox. DO NOT REMOVE THIS LINE.\n// var a = bodyEl.offsetWidth + 1;\n// fn();\n// });\n// };\n\n// });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$modal', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n backdropAnimation: 'am-fade',\n prefixClass: 'modal',\n prefixEvent: 'modal',\n placement: 'top',\n template: 'modal/modal.tpl.html',\n contentTemplate: false,\n container: false,\n element: null,\n backdrop: true,\n keyboard: true,\n html: false,\n show: true\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $timeout, $sce, dimensions) {\n\n var forEach = angular.forEach;\n var trim = String.prototype.trim;\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n var bodyElement = angular.element($window.document.body);\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n\n function ModalFactory(config) {\n\n var $modal = {};\n\n // Common vars\n var options = $modal.$options = angular.extend({}, defaults, config);\n $modal.$promise = fetchTemplate(options.template);\n var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(!options.element && !options.container) {\n options.container = 'body';\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $modal.$id = options.id || options.element && options.element.attr('id') || '';\n\n // Support scope as string options\n forEach(['title', 'content'], function(key) {\n if(options[key]) scope[key] = $sce.trustAsHtml(options[key]);\n });\n\n // Provide scope helpers\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $modal.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $modal.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $modal.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $modal.$isShown = scope.$isShown = false;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $modal.$promise = $modal.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]).removeAttr('ng-bind').html(contentTemplate);\n // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n if(!config.template) contentEl.next().remove();\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize modal\n var modalLinker, modalElement;\n var backdropElement = angular.element('
');\n backdropElement.css({position:'fixed', top:'0px', left:'0px', bottom:'0px', right:'0px', 'z-index': 1038});\n $modal.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n modalLinker = $compile(template);\n $modal.init();\n });\n\n $modal.init = function() {\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n $modal.show();\n });\n }\n\n };\n\n $modal.destroy = function() {\n\n // Remove element\n if(modalElement) {\n modalElement.remove();\n modalElement = null;\n }\n if(backdropElement) {\n backdropElement.remove();\n backdropElement = null;\n }\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $modal.show = function() {\n if($modal.$isShown) return;\n\n var parent, after;\n if(angular.isElement(options.container)) {\n parent = options.container;\n after = options.container[0].lastChild ? angular.element(options.container[0].lastChild) : null;\n } else {\n if (options.container) {\n parent = findElement(options.container);\n after = parent[0] && parent[0].lastChild ? angular.element(parent[0].lastChild) : null;\n } else {\n parent = null;\n after = options.element;\n }\n }\n\n // Fetch a cloned element linked from template\n modalElement = $modal.$element = modalLinker(scope, function(clonedElement, scope) {});\n\n if(scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n return;\n }\n\n // Set the initial positioning.\n modalElement.css({display: 'block'}).addClass(options.placement);\n\n // Options: animation\n if(options.animation) {\n if(options.backdrop) {\n backdropElement.addClass(options.backdropAnimation);\n }\n modalElement.addClass(options.animation);\n }\n\n if(options.backdrop) {\n $animate.enter(backdropElement, bodyElement, null);\n }\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.enter(modalElement, parent, after, enterAnimateCallback);\n if(promise && promise.then) promise.then(enterAnimateCallback);\n\n $modal.$isShown = scope.$isShown = true;\n safeDigest(scope);\n // Focus once the enter-animation has started\n // Weird PhantomJS bug hack\n var el = modalElement[0];\n requestAnimationFrame(function() {\n el.focus();\n });\n\n bodyElement.addClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n }\n\n // Bind events\n if(options.backdrop) {\n modalElement.on('click', hideOnBackdropClick);\n backdropElement.on('click', hideOnBackdropClick);\n backdropElement.on('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.on('keyup', $modal.$onKeyUp);\n }\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $modal);\n }\n\n $modal.hide = function() {\n if(!$modal.$isShown) return;\n\n if(scope.$emit(options.prefixEvent + '.hide.before', $modal).defaultPrevented) {\n return;\n }\n var promise = $animate.leave(modalElement, leaveAnimateCallback);\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n if(options.backdrop) {\n $animate.leave(backdropElement);\n }\n $modal.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.backdrop) {\n modalElement.off('click', hideOnBackdropClick);\n backdropElement.off('click', hideOnBackdropClick);\n backdropElement.off('wheel', preventEventDefault);\n }\n if(options.keyboard) {\n modalElement.off('keyup', $modal.$onKeyUp);\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $modal);\n bodyElement.removeClass(options.prefixClass + '-open');\n if(options.animation) {\n bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n }\n }\n\n $modal.toggle = function() {\n\n $modal.$isShown ? $modal.hide() : $modal.show();\n\n };\n\n $modal.focus = function() {\n modalElement[0].focus();\n };\n\n // Protected methods\n\n $modal.$onKeyUp = function(evt) {\n\n if (evt.which === 27 && $modal.$isShown) {\n $modal.hide();\n evt.stopPropagation();\n }\n\n };\n\n // Private methods\n\n function hideOnBackdropClick(evt) {\n if(evt.target !== evt.currentTarget) return;\n options.backdrop === 'static' ? $modal.focus() : $modal.hide();\n }\n\n function preventEventDefault(evt) {\n evt.preventDefault();\n }\n\n return $modal;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return ModalFactory;\n\n };\n\n })\n\n .directive('bsModal', function($window, $sce, $modal) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope, element: element, show: false};\n angular.forEach(['template', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['backdrop', 'keyboard', 'html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n });\n });\n\n // Support scope as an object\n attr.bsModal && scope.$watch(attr.bsModal, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n }, true);\n\n // Initialize modal\n var modal = $modal(options);\n\n // Trigger\n element.on(attr.trigger || 'click', modal.toggle);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (modal) modal.destroy();\n options = null;\n modal = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.navbar', [])\n\n .provider('$navbar', function() {\n\n var defaults = this.defaults = {\n activeClass: 'active',\n routeAttr: 'data-match-route',\n strict: false\n };\n\n this.$get = function() {\n return {defaults: defaults};\n };\n\n })\n\n .directive('bsNavbar', function($window, $location, $navbar) {\n\n var defaults = $navbar.defaults;\n\n return {\n restrict: 'A',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = angular.copy(defaults);\n angular.forEach(Object.keys(defaults), function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // Watch for the $location\n scope.$watch(function() {\n\n return $location.path();\n\n }, function(newValue, oldValue) {\n\n var liElements = element[0].querySelectorAll('li[' + options.routeAttr + ']');\n\n angular.forEach(liElements, function(li) {\n\n var liElement = angular.element(li);\n var pattern = liElement.attr(options.routeAttr).replace('/', '\\\\/');\n if(options.strict) {\n pattern = '^' + pattern + '$';\n }\n var regexp = new RegExp(pattern, 'i');\n\n if(regexp.test(newValue)) {\n liElement.addClass(options.activeClass);\n } else {\n liElement.removeClass(options.activeClass);\n }\n\n });\n\n });\n\n }\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])\n\n .provider('$popover', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n // uncommenting the next two lines will break backwards compatability\n // prefixClass: 'popover',\n // prefixEvent: 'popover',\n container: false,\n target: false,\n placement: 'right',\n template: 'popover/popover.tpl.html',\n contentTemplate: false,\n trigger: 'click',\n keyboard: true,\n html: false,\n title: '',\n content: '',\n delay: 0,\n autoClose: false\n };\n\n this.$get = function($tooltip) {\n\n function PopoverFactory(element, config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n var $popover = $tooltip(element, options);\n\n // Support scope as string options [/*title, */content]\n if(options.content) {\n $popover.$scope.content = options.content;\n }\n\n return $popover;\n\n }\n\n return PopoverFactory;\n\n };\n\n })\n\n .directive('bsPopover', function($window, $sce, $popover) {\n\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'customClass', 'autoClose', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoClose'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // Support scope as data-attrs\n angular.forEach(['title', 'content'], function(key) {\n attr[key] && attr.$observe(key, function(newValue, oldValue) {\n scope[key] = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n });\n });\n\n // Support scope as an object\n attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.content = newValue;\n }\n angular.isDefined(oldValue) && requestAnimationFrame(function() {\n popover && popover.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(popover),?/i);\n newValue === true ? popover.show() : popover.hide();\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!popover || !angular.isDefined(newValue)) return;\n popover.setViewport(newValue);\n });\n\n // Initialize popover\n var popover = $popover(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (popover) popover.destroy();\n options = null;\n popover = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.scrollspy', ['mgcrea.ngStrap.helpers.debounce', 'mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$scrollspy', function() {\n\n // Pool of registered spies\n var spies = this.$$spies = {};\n\n var defaults = this.defaults = {\n debounce: 150,\n throttle: 100,\n offset: 100\n };\n\n this.$get = function($window, $document, $rootScope, dimensions, debounce, throttle) {\n\n var windowEl = angular.element($window);\n var docEl = angular.element($document.prop('documentElement'));\n var bodyEl = angular.element($window.document.body);\n\n // Helper functions\n\n function nodeName(element, name) {\n return element[0].nodeName && element[0].nodeName.toLowerCase() === name.toLowerCase();\n }\n\n function ScrollSpyFactory(config) {\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n if(!options.element) options.element = bodyEl;\n var isWindowSpy = nodeName(options.element, 'body');\n var scrollEl = isWindowSpy ? windowEl : options.element;\n var scrollId = isWindowSpy ? 'window' : options.id;\n\n // Use existing spy\n if(spies[scrollId]) {\n spies[scrollId].$$count++;\n return spies[scrollId];\n }\n\n var $scrollspy = {};\n\n // Private vars\n var unbindViewContentLoaded, unbindIncludeContentLoaded;\n var trackedElements = $scrollspy.$trackedElements = [];\n var sortedElements = [];\n var activeTarget;\n var debouncedCheckPosition;\n var throttledCheckPosition;\n var debouncedCheckOffsets;\n var viewportHeight;\n var scrollTop;\n\n $scrollspy.init = function() {\n\n // Setup internal ref counter\n this.$$count = 1;\n\n // Bind events\n debouncedCheckPosition = debounce(this.checkPosition, options.debounce);\n throttledCheckPosition = throttle(this.checkPosition, options.throttle);\n scrollEl.on('click', this.checkPositionWithEventLoop);\n windowEl.on('resize', debouncedCheckPosition);\n scrollEl.on('scroll', throttledCheckPosition);\n\n debouncedCheckOffsets = debounce(this.checkOffsets, options.debounce);\n unbindViewContentLoaded = $rootScope.$on('$viewContentLoaded', debouncedCheckOffsets);\n unbindIncludeContentLoaded = $rootScope.$on('$includeContentLoaded', debouncedCheckOffsets);\n debouncedCheckOffsets();\n\n // Register spy for reuse\n if(scrollId) {\n spies[scrollId] = $scrollspy;\n }\n\n };\n\n $scrollspy.destroy = function() {\n\n // Check internal ref counter\n this.$$count--;\n if(this.$$count > 0) {\n return;\n }\n\n // Unbind events\n scrollEl.off('click', this.checkPositionWithEventLoop);\n windowEl.off('resize', debouncedCheckPosition);\n scrollEl.off('scroll', throttledCheckPosition);\n unbindViewContentLoaded();\n unbindIncludeContentLoaded();\n if (scrollId) {\n delete spies[scrollId];\n }\n };\n\n $scrollspy.checkPosition = function() {\n\n // Not ready yet\n if(!sortedElements.length) return;\n\n // Calculate the scroll position\n scrollTop = (isWindowSpy ? $window.pageYOffset : scrollEl.prop('scrollTop')) || 0;\n\n // Calculate the viewport height for use by the components\n viewportHeight = Math.max($window.innerHeight, docEl.prop('clientHeight'));\n\n // Activate first element if scroll is smaller\n if(scrollTop < sortedElements[0].offsetTop && activeTarget !== sortedElements[0].target) {\n return $scrollspy.$activateElement(sortedElements[0]);\n }\n\n // Activate proper element\n for (var i = sortedElements.length; i--;) {\n if(angular.isUndefined(sortedElements[i].offsetTop) || sortedElements[i].offsetTop === null) continue;\n if(activeTarget === sortedElements[i].target) continue;\n if(scrollTop < sortedElements[i].offsetTop) continue;\n if(sortedElements[i + 1] && scrollTop > sortedElements[i + 1].offsetTop) continue;\n return $scrollspy.$activateElement(sortedElements[i]);\n }\n\n };\n\n $scrollspy.checkPositionWithEventLoop = function() {\n // IE 9 throws an error if we use 'this' instead of '$scrollspy'\n // in this setTimeout call\n setTimeout($scrollspy.checkPosition, 1);\n };\n\n // Protected methods\n\n $scrollspy.$activateElement = function(element) {\n if(activeTarget) {\n var activeElement = $scrollspy.$getTrackedElement(activeTarget);\n if(activeElement) {\n activeElement.source.removeClass('active');\n if(nodeName(activeElement.source, 'li') && nodeName(activeElement.source.parent().parent(), 'li')) {\n activeElement.source.parent().parent().removeClass('active');\n }\n }\n }\n activeTarget = element.target;\n element.source.addClass('active');\n if(nodeName(element.source, 'li') && nodeName(element.source.parent().parent(), 'li')) {\n element.source.parent().parent().addClass('active');\n }\n };\n\n $scrollspy.$getTrackedElement = function(target) {\n return trackedElements.filter(function(obj) {\n return obj.target === target;\n })[0];\n };\n\n // Track offsets behavior\n\n $scrollspy.checkOffsets = function() {\n\n angular.forEach(trackedElements, function(trackedElement) {\n var targetElement = document.querySelector(trackedElement.target);\n trackedElement.offsetTop = targetElement ? dimensions.offset(targetElement).top : null;\n if(options.offset && trackedElement.offsetTop !== null) trackedElement.offsetTop -= options.offset * 1;\n });\n\n sortedElements = trackedElements\n .filter(function(el) {\n return el.offsetTop !== null;\n })\n .sort(function(a, b) {\n return a.offsetTop - b.offsetTop;\n });\n\n debouncedCheckPosition();\n\n };\n\n $scrollspy.trackElement = function(target, source) {\n trackedElements.push({target: target, source: source});\n };\n\n $scrollspy.untrackElement = function(target, source) {\n var toDelete;\n for (var i = trackedElements.length; i--;) {\n if(trackedElements[i].target === target && trackedElements[i].source === source) {\n toDelete = i;\n break;\n }\n }\n trackedElements = trackedElements.splice(toDelete, 1);\n };\n\n $scrollspy.activate = function(i) {\n trackedElements[i].addClass('active');\n };\n\n // Initialize plugin\n\n $scrollspy.init();\n return $scrollspy;\n\n }\n\n return ScrollSpyFactory;\n\n };\n\n })\n\n .directive('bsScrollspy', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'EAC',\n link: function postLink(scope, element, attr) {\n\n var options = {scope: scope};\n angular.forEach(['offset', 'target'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n var scrollspy = $scrollspy(options);\n scrollspy.trackElement(options.target, element);\n\n scope.$on('$destroy', function() {\n if (scrollspy) {\n scrollspy.untrackElement(options.target, element);\n scrollspy.destroy();\n }\n options = null;\n scrollspy = null;\n });\n\n }\n };\n\n })\n\n\n .directive('bsScrollspyList', function($rootScope, debounce, dimensions, $scrollspy) {\n\n return {\n restrict: 'A',\n compile: function postLink(element, attr) {\n var children = element[0].querySelectorAll('li > a[href]');\n angular.forEach(children, function(child) {\n var childEl = angular.element(child);\n childEl.parent().attr('bs-scrollspy', '').attr('data-target', childEl.attr('href'));\n });\n }\n\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.select', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$select', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'select',\n prefixEvent: '$select',\n placement: 'bottom-left',\n template: 'select/select.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n multiple: false,\n allNoneButtons: false,\n sort: true,\n caretHtml: ' ',\n placeholder: 'Choose among the following...',\n allText: 'All',\n noneText: 'None',\n maxLength: 3,\n maxLengthHtml: 'selected',\n iconCheckmark: 'glyphicon glyphicon-ok'\n };\n\n this.$get = function($window, $document, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n\n function SelectFactory(element, controller, config) {\n\n var $select = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $select = $tooltip(element, options);\n var scope = $select.$scope;\n\n scope.$matches = [];\n if (options.multiple) {\n scope.$activeIndex = [];\n }\n else {\n scope.$activeIndex = -1;\n }\n scope.$isMultiple = options.multiple;\n scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;\n scope.$iconCheckmark = options.iconCheckmark;\n scope.$allText = options.allText;\n scope.$noneText = options.noneText;\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $select.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $select.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $select.$isVisible();\n };\n\n scope.$isActive = function(index) {\n return $select.$isActive(index);\n };\n\n scope.$selectAll = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (!scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n scope.$selectNone = function () {\n for (var i = 0; i < scope.$matches.length; i++) {\n if (scope.$isActive(i)) {\n scope.$select(i);\n }\n }\n };\n\n // Public methods\n\n $select.update = function(matches) {\n scope.$matches = matches;\n $select.$updateActiveIndex();\n };\n\n $select.activate = function(index) {\n if(options.multiple) {\n $select.$isActive(index) ? scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1) : scope.$activeIndex.push(index);\n if(options.sort) scope.$activeIndex.sort();\n } else {\n scope.$activeIndex = index;\n }\n return scope.$activeIndex;\n };\n\n $select.select = function(index) {\n var value = scope.$matches[index].value;\n scope.$apply(function() {\n $select.activate(index);\n if(options.multiple) {\n controller.$setViewValue(scope.$activeIndex.map(function(index) {\n return scope.$matches[index].value;\n }));\n } else {\n controller.$setViewValue(value);\n // Hide if single select\n $select.hide();\n }\n });\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $select);\n };\n\n // Protected methods\n\n $select.$updateActiveIndex = function() {\n if(controller.$modelValue && scope.$matches.length) {\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n scope.$activeIndex = controller.$modelValue.map(function(value) {\n return $select.$getIndex(value);\n });\n } else {\n scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n }\n } else if(scope.$activeIndex >= scope.$matches.length) {\n scope.$activeIndex = options.multiple ? [] : 0;\n }\n };\n\n $select.$isVisible = function() {\n if(!options.minLength || !controller) {\n return scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && controller.$viewValue.length >= options.minLength;\n };\n\n $select.$isActive = function(index) {\n if(options.multiple) {\n return scope.$activeIndex.indexOf(index) !== -1;\n } else {\n return scope.$activeIndex === index;\n }\n };\n\n $select.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $select.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n targetEl.triggerHandler('click');\n }\n };\n\n $select.$onKeyDown = function(evt) {\n if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // release focus on tab\n if (options.multiple && evt.keyCode === 9) {\n return $select.hide();\n }\n\n // Select with enter\n if(!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {\n return $select.select(scope.$activeIndex);\n }\n\n if (!options.multiple) {\n // Navigate with keyboard\n if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 38 && scope.$activeIndex < 0) scope.$activeIndex = scope.$matches.length - 1;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n }\n };\n\n // Overrides\n\n var _show = $select.show;\n $select.show = function() {\n _show();\n if(options.multiple) {\n $select.$element.addClass('select-multiple');\n }\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $select.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $select.hide;\n $select.hide = function() {\n if(!options.multiple && !controller.$modelValue) {\n scope.$activeIndex = -1;\n }\n $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $select.$onKeyDown);\n }\n _hide(true);\n };\n\n return $select;\n\n }\n\n SelectFactory.defaults = defaults;\n return SelectFactory;\n\n };\n\n })\n\n .directive('bsSelect', function($window, $parse, $q, $select, $parseOptions) {\n\n var defaults = $select.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, placeholder: defaults.placeholder};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'placeholder', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id', 'sort', 'caretHtml', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'allNoneButtons', 'sort'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Only parse data-multiple. Angular sets existence attributes to true (multiple/required/etc), they apply this\n // to data-multiple as well for some reason, so we'll parse this ourselves and disregard multiple\n var dataMultiple = element.attr('data-multiple');\n if(angular.isDefined(dataMultiple)) {\n if(falseValueRegExp.test(dataMultiple))\n options.multiple = false;\n else\n options.multiple = dataMultiple;\n }\n\n // Add support for select markup\n if(element[0].nodeName.toLowerCase() === 'select') {\n var inputEl = element;\n inputEl.css('display', 'none');\n element = angular.element('');\n inputEl.after(element);\n }\n\n // Build proper bsOptions\n var parsedOptions = $parseOptions(attr.bsOptions);\n\n // Initialize select\n var select = $select(element, controller, options);\n\n // Watch bsOptions values before filtering for changes\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n scope.$watchCollection(watchedOptions, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n select.update(values);\n controller.$render();\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n select.$updateActiveIndex();\n controller.$render();\n }, true);\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n var selected, index;\n if(options.multiple && angular.isArray(controller.$modelValue)) {\n selected = controller.$modelValue.map(function(value) {\n index = select.$getIndex(value);\n return angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }).filter(angular.isDefined);\n if(selected.length > (options.maxLength || defaults.maxLength)) {\n selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml);\n } else {\n selected = selected.join(', ');\n }\n } else {\n index = select.$getIndex(controller.$modelValue);\n selected = angular.isDefined(index) ? select.$scope.$matches[index].label : false;\n }\n element.html((selected ? selected : options.placeholder) + (options.caretHtml ? options.caretHtml : defaults.caretHtml));\n };\n\n if(options.multiple){\n controller.$isEmpty = function(value){\n return !value || value.length === 0;\n };\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (select) select.destroy();\n options = null;\n select = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.tab', [])\n\n .provider('$tab', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n template: 'tab/tab.tpl.html',\n navClass: 'nav-tabs',\n activeClass: 'active'\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'navClass', 'activeClass'], function(key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // Publish options on scope\n $scope.$navClass = self.$options.navClass;\n $scope.$activeClass = self.$options.activeClass;\n\n self.$panes = $scope.$panes = [];\n\n // Please use $activePaneChangeListeners if you use `bsActivePane`\n // Because we removed `ngModel` as default, we rename viewChangeListeners to\n // activePaneChangeListeners to make more sense.\n self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n if(angular.isUndefined(self.$panes.$active)) {\n $scope.$setActive(pane.name || 0);\n }\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var active = self.$panes.$active;\n var activeIndex;\n if(angular.isString(active)) {\n activeIndex = self.$panes.map(function(pane) {\n return pane.name;\n }).indexOf(active);\n } else {\n activeIndex = self.$panes.$active;\n }\n\n // remove pane from $panes array\n self.$panes.splice(index, 1);\n\n if (index < activeIndex) {\n // we removed a pane before the active pane, so we need to\n // decrement the active pane index\n activeIndex--;\n }\n else if (index === activeIndex && activeIndex === self.$panes.length) {\n // we remove the active pane and it was the one at the end,\n // so select the previous one\n activeIndex--;\n }\n if(activeIndex >= 0 && activeIndex < self.$panes.length) {\n self.$setActive(self.$panes[activeIndex].name || activeIndex);\n } else {\n self.$setActive();\n }\n };\n\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$activePaneChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$isActive = $scope.$isActive = function($pane, $index) {\n return self.$panes.$active === $pane.name || self.$panes.$active === $index;\n };\n\n };\n\n this.$get = function() {\n var $tab = {};\n $tab.defaults = defaults;\n $tab.controller = controller;\n return $tab;\n };\n\n })\n\n .directive('bsTabs', function($window, $animate, $tab, $parse) {\n\n var defaults = $tab.defaults;\n\n return {\n require: ['?ngModel', 'bsTabs'],\n transclude: true,\n scope: true,\n controller: ['$scope', '$element', '$attrs', $tab.controller],\n templateUrl: function(element, attr) {\n return attr.template || defaults.template;\n },\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // 'ngModel' does interfere with form validation\n // and status, use `bsActivePane` instead to avoid it\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n bsTabsCtrl.$setActive(modelValue);\n return modelValue;\n });\n\n }\n\n if (attrs.bsActivePane) {\n // adapted from angularjs ngModelController bindings\n // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n // Update bsActivePane value with change\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n });\n\n // watch bsActivePane for value changes\n scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n bsTabsCtrl.$setActive(newValue);\n }, true);\n }\n }\n };\n\n })\n\n .directive('bsPane', function($window, $animate, $sce) {\n\n return {\n require: ['^?ngModel', '^bsTabs'],\n scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // Add base class\n element.addClass('tab-pane');\n\n // Observe title attribute for change\n attrs.$observe('title', function(newValue, oldValue) {\n scope.title = $sce.trustAsHtml(newValue);\n });\n\n // Save tab name into scope\n scope.name = attrs.name;\n\n // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\n }\n\n attrs.$observe('disabled', function(newValue, oldValue) {\n scope.disabled = scope.$eval(newValue);\n });\n\n // Push pane to parent bsTabs controller\n bsTabsCtrl.$push(scope);\n\n // remove pane from tab controller when pane is destroyed\n scope.$on('$destroy', function() {\n bsTabsCtrl.$remove(scope);\n });\n\n function render() {\n var index = bsTabsCtrl.$panes.indexOf(scope);\n $animate[bsTabsCtrl.$isActive(scope, index) ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.timepicker', [\n 'mgcrea.ngStrap.helpers.dateParser',\n 'mgcrea.ngStrap.helpers.dateFormatter',\n 'mgcrea.ngStrap.tooltip'])\n\n .provider('$timepicker', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n //uncommenting the following line will break backwards compatability\n // prefixEvent: 'timepicker',\n prefixClass: 'timepicker',\n placement: 'bottom-left',\n template: 'timepicker/timepicker.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n // lang: $locale.id,\n useNative: true,\n timeType: 'date',\n timeFormat: 'shortTime',\n timezone: null,\n modelTimeFormat: null,\n autoclose: false,\n minTime: -Infinity,\n maxTime: +Infinity,\n length: 5,\n hourStep: 1,\n minuteStep: 5,\n secondStep: 5,\n roundDisplay: false,\n iconUp: 'glyphicon glyphicon-chevron-up',\n iconDown: 'glyphicon glyphicon-chevron-down',\n arrowBehavior: 'pager'\n };\n\n this.$get = function($window, $document, $rootScope, $sce, $dateFormatter, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var isTouch = ('createTouch' in $window.document) && isNative;\n if(!defaults.lang) defaults.lang = $dateFormatter.getDefaultLocale();\n\n function timepickerFactory(element, controller, config) {\n\n var $timepicker = $tooltip(element, angular.extend({}, defaults, config));\n var parentScope = config.scope;\n var options = $timepicker.$options;\n var scope = $timepicker.$scope;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n function floorMinutes(time)\n {\n // coeff used to floor current time to nearest minuteStep interval\n var coeff = 1000 * 60 * options.minuteStep;\n return new Date(Math.floor(time.getTime() / coeff) * coeff);\n }\n\n // View vars\n\n var selectedIndex = 0;\n var defaultDate = options.roundDisplay ? floorMinutes(new Date()) : new Date();\n var startDate = controller.$dateValue || defaultDate;\n var viewDate = {hour: startDate.getHours(), meridian: startDate.getHours() < 12, minute: startDate.getMinutes(), second: startDate.getSeconds(), millisecond: startDate.getMilliseconds()};\n\n var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n var hoursFormat = $dateFormatter.hoursFormat(format),\n timeSeparator = $dateFormatter.timeSeparator(format),\n minutesFormat = $dateFormatter.minutesFormat(format),\n secondsFormat = $dateFormatter.secondsFormat(format),\n showSeconds = $dateFormatter.showSeconds(format),\n showAM = $dateFormatter.showAM(format);\n\n scope.$iconUp = options.iconUp;\n scope.$iconDown = options.iconDown;\n\n // Scope methods\n\n scope.$select = function(date, index) {\n $timepicker.select(date, index);\n };\n scope.$moveIndex = function(value, index) {\n $timepicker.$moveIndex(value, index);\n };\n scope.$switchMeridian = function(date) {\n $timepicker.switchMeridian(date);\n };\n\n // Public methods\n\n $timepicker.update = function(date) {\n // console.warn('$timepicker.update() newValue=%o', date);\n if(angular.isDate(date) && !isNaN(date.getTime())) {\n $timepicker.$date = date;\n angular.extend(viewDate, {hour: date.getHours(), minute: date.getMinutes(), second: date.getSeconds(), millisecond: date.getMilliseconds()});\n $timepicker.$build();\n } else if(!$timepicker.$isBuilt) {\n $timepicker.$build();\n }\n };\n\n $timepicker.select = function(date, index, keep) {\n // console.warn('$timepicker.select', date, scope.$mode);\n if(!controller.$dateValue || isNaN(controller.$dateValue.getTime())) controller.$dateValue = new Date(1970, 0, 1);\n if(!angular.isDate(date)) date = new Date(date);\n if(index === 0) controller.$dateValue.setHours(date.getHours());\n else if(index === 1) controller.$dateValue.setMinutes(date.getMinutes());\n else if(index === 2) controller.$dateValue.setSeconds(date.getSeconds());\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n if(options.autoclose && !keep) {\n $timeout(function() { $timepicker.hide(true); });\n }\n };\n\n $timepicker.switchMeridian = function(date) {\n if (!controller.$dateValue || isNaN(controller.$dateValue.getTime())) {\n return;\n }\n var hours = (date || controller.$dateValue).getHours();\n controller.$dateValue.setHours(hours < 12 ? hours + 12 : hours - 12);\n controller.$setViewValue(angular.copy(controller.$dateValue));\n controller.$render();\n };\n\n // Protected methods\n\n $timepicker.$build = function() {\n // console.warn('$timepicker.$build() viewDate=%o', viewDate);\n var i, midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n var hours = [], hour;\n for(i = 0; i < options.length; i++) {\n hour = new Date(1970, 0, 1, viewDate.hour - (midIndex - i) * options.hourStep);\n hours.push({date: hour, label: formatDate(hour, hoursFormat), selected: $timepicker.$date && $timepicker.$isSelected(hour, 0), disabled: $timepicker.$isDisabled(hour, 0)});\n }\n var minutes = [], minute;\n for(i = 0; i < options.length; i++) {\n minute = new Date(1970, 0, 1, 0, viewDate.minute - (midIndex - i) * options.minuteStep);\n minutes.push({date: minute, label: formatDate(minute, minutesFormat), selected: $timepicker.$date && $timepicker.$isSelected(minute, 1), disabled: $timepicker.$isDisabled(minute, 1)});\n }\n var seconds = [], second;\n for(i = 0; i < options.length; i++) {\n second = new Date(1970, 0, 1, 0, 0, viewDate.second - (midIndex - i) * options.secondStep);\n seconds.push({date: second, label: formatDate(second, secondsFormat), selected: $timepicker.$date && $timepicker.$isSelected(second, 2), disabled: $timepicker.$isDisabled(second, 2)});\n }\n\n var rows = [];\n for(i = 0; i < options.length; i++) {\n if (showSeconds) {\n rows.push([hours[i], minutes[i], seconds[i]]);\n } else {\n rows.push([hours[i], minutes[i]]);\n }\n }\n scope.rows = rows;\n scope.showSeconds = showSeconds;\n scope.showAM = showAM;\n scope.isAM = ($timepicker.$date || hours[midIndex].date).getHours() < 12;\n scope.timeSeparator = timeSeparator;\n $timepicker.$isBuilt = true;\n };\n\n $timepicker.$isSelected = function(date, index) {\n if(!$timepicker.$date) return false;\n else if(index === 0) {\n return date.getHours() === $timepicker.$date.getHours();\n } else if(index === 1) {\n return date.getMinutes() === $timepicker.$date.getMinutes();\n } else if(index === 2) {\n return date.getSeconds() === $timepicker.$date.getSeconds();\n }\n };\n\n $timepicker.$isDisabled = function(date, index) {\n var selectedTime;\n if(index === 0) {\n selectedTime = date.getTime() + viewDate.minute * 6e4 + viewDate.second * 1e3;\n } else if(index === 1) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.second * 1e3;\n } else if(index === 2) {\n selectedTime = date.getTime() + viewDate.hour * 36e5 + viewDate.minute * 6e4;\n }\n return selectedTime < options.minTime * 1 || selectedTime > options.maxTime * 1;\n };\n\n scope.$arrowAction = function (value, index) {\n if (options.arrowBehavior === 'picker') {\n $timepicker.$setTimeByStep(value,index);\n } else {\n $timepicker.$moveIndex(value,index);\n }\n };\n\n $timepicker.$setTimeByStep = function(value, index) {\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n if (index === 0) {\n newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n }\n else if (index === 1) {\n newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\n }\n else if (index === 2) {\n newDate.setSeconds(seconds - (parseInt(options.secondStep, 10) * value));\n }\n $timepicker.select(newDate, index, true);\n };\n\n $timepicker.$moveIndex = function(value, index) {\n var targetDate;\n if(index === 0) {\n targetDate = new Date(1970, 0, 1, viewDate.hour + (value * options.length), viewDate.minute, viewDate.second);\n angular.extend(viewDate, {hour: targetDate.getHours()});\n } else if(index === 1) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute + (value * options.length * options.minuteStep), viewDate.second);\n angular.extend(viewDate, {minute: targetDate.getMinutes()});\n } else if(index === 2) {\n targetDate = new Date(1970, 0, 1, viewDate.hour, viewDate.minute, viewDate.second + (value * options.length * options.secondStep));\n angular.extend(viewDate, {second: targetDate.getSeconds()});\n }\n $timepicker.$build();\n };\n\n $timepicker.$onMouseDown = function(evt) {\n // Prevent blur on mousedown on .dropdown-menu\n if(evt.target.nodeName.toLowerCase() !== 'input') evt.preventDefault();\n evt.stopPropagation();\n // Emulate click for mobile devices\n if(isTouch) {\n var targetEl = angular.element(evt.target);\n if(targetEl[0].nodeName.toLowerCase() !== 'button') {\n targetEl = targetEl.parent();\n }\n targetEl.triggerHandler('click');\n }\n };\n\n $timepicker.$onKeyDown = function(evt) {\n if (!/(38|37|39|40|13)/.test(evt.keyCode) || evt.shiftKey || evt.altKey) return;\n evt.preventDefault();\n evt.stopPropagation();\n\n // Close on enter\n if(evt.keyCode === 13) return $timepicker.hide(true);\n\n // Navigate with keyboard\n var newDate = new Date($timepicker.$date);\n var hours = newDate.getHours(), hoursLength = formatDate(newDate, hoursFormat).length;\n var minutes = newDate.getMinutes(), minutesLength = formatDate(newDate, minutesFormat).length;\n var seconds = newDate.getSeconds(), secondsLength = formatDate(newDate, secondsFormat).length;\n var sepLength = 1;\n var lateralMove = /(37|39)/.test(evt.keyCode);\n var count = 2 + showSeconds * 1 + showAM * 1;\n\n // Navigate indexes (left, right)\n if (lateralMove) {\n if(evt.keyCode === 37) selectedIndex = selectedIndex < 1 ? count - 1 : selectedIndex - 1;\n else if(evt.keyCode === 39) selectedIndex = selectedIndex < count - 1 ? selectedIndex + 1 : 0;\n }\n\n // Update values (up, down)\n var selectRange = [0, hoursLength];\n var incr = 0;\n if (evt.keyCode === 38) incr = -1;\n if (evt.keyCode === 40) incr = +1;\n var isSeconds = selectedIndex === 2 && showSeconds;\n var isMeridian = selectedIndex === 2 && !showSeconds || selectedIndex === 3 && showSeconds;\n if(selectedIndex === 0) {\n newDate.setHours(hours + incr*parseInt(options.hourStep, 10));\n // re-calculate hours length because we have changed hours value\n hoursLength = formatDate(newDate, hoursFormat).length;\n selectRange = [0, hoursLength];\n } else if(selectedIndex === 1) {\n newDate.setMinutes(minutes + incr*parseInt(options.minuteStep, 10));\n // re-calculate minutes length because we have changes minutes value\n minutesLength = formatDate(newDate, minutesFormat).length;\n selectRange = [hoursLength + sepLength, minutesLength];\n } else if(isSeconds) {\n newDate.setSeconds(seconds + incr*parseInt(options.secondStep, 10));\n // re-calculate seconds length because we have changes seconds value\n secondsLength = formatDate(newDate, secondsFormat).length;\n selectRange = [hoursLength + sepLength + minutesLength + sepLength, secondsLength];\n } else if(isMeridian) {\n if(!lateralMove) $timepicker.switchMeridian();\n selectRange = [hoursLength + sepLength + minutesLength + sepLength + (secondsLength + sepLength)*showSeconds, 2];\n }\n $timepicker.select(newDate, selectedIndex, true);\n createSelection(selectRange[0], selectRange[1]);\n parentScope.$digest();\n };\n\n // Private\n\n function createSelection(start, length) {\n var end = start + length;\n if(element[0].createTextRange) {\n var selRange = element[0].createTextRange();\n selRange.collapse(true);\n selRange.moveStart('character', start);\n selRange.moveEnd('character', end);\n selRange.select();\n } else if(element[0].setSelectionRange) {\n element[0].setSelectionRange(start, end);\n } else if(angular.isUndefined(element[0].selectionStart)) {\n element[0].selectionStart = start;\n element[0].selectionEnd = end;\n }\n }\n\n function focusElement() {\n element[0].focus();\n }\n\n // Overrides\n\n var _init = $timepicker.init;\n $timepicker.init = function() {\n if(isNative && options.useNative) {\n element.prop('type', 'time');\n element.css('-webkit-appearance', 'textfield');\n return;\n } else if(isTouch) {\n element.prop('type', 'text');\n element.attr('readonly', 'true');\n element.on('click', focusElement);\n }\n _init();\n };\n\n var _destroy = $timepicker.destroy;\n $timepicker.destroy = function() {\n if(isNative && options.useNative) {\n element.off('click', focusElement);\n }\n _destroy();\n };\n\n var _show = $timepicker.show;\n $timepicker.show = function() {\n _show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $timepicker.$onKeyDown);\n }\n }, 0, false);\n };\n\n var _hide = $timepicker.hide;\n $timepicker.hide = function(blur) {\n if(!$timepicker.$isShown) return;\n $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $timepicker.$onKeyDown);\n }\n _hide(blur);\n };\n\n return $timepicker;\n\n }\n\n timepickerFactory.defaults = defaults;\n return timepickerFactory;\n\n };\n\n })\n\n\n .directive('bsTimepicker', function($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n var defaults = $timepicker.defaults;\n var isNative = /(ip(a|o)d|iphone|android)/ig.test($window.navigator.userAgent);\n var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope, controller: controller};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'autoclose', 'timeType', 'timeFormat', 'timezone', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'secondStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'roundDisplay', 'id', 'prefixClass', 'prefixEvent'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'autoclose', 'useNative', 'roundDisplay'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!timepicker || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(timepicker),?/i);\n newValue === true ? timepicker.show() : timepicker.hide();\n });\n\n // Initialize timepicker\n if(isNative && (options.useNative || defaults.useNative)) options.timeFormat = 'HH:mm';\n var timepicker = $timepicker(element, controller, options);\n options = timepicker.$options;\n\n var lang = options.lang;\n var formatDate = function(date, format, timezone) {\n return $dateFormatter.formatDate(date, format, lang, timezone);\n };\n\n // Initialize parser\n var dateParser = $dateParser({format: options.timeFormat, lang: lang});\n\n // Observe attributes for changes\n angular.forEach(['minTime', 'maxTime'], function(key) {\n // console.warn('attr.$observe(%s)', key, attr[key]);\n angular.isDefined(attr[key]) && attr.$observe(key, function(newValue) {\n timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n !isNaN(timepicker.$options[key]) && timepicker.$build();\n validateAgainstMinMaxTime(controller.$dateValue);\n });\n });\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue, controller.$dateValue);\n timepicker.update(controller.$dateValue);\n }, true);\n\n function validateAgainstMinMaxTime(parsedTime) {\n if (!angular.isDate(parsedTime)) return;\n var isMinValid = isNaN(options.minTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) >= options.minTime;\n var isMaxValid = isNaN(options.maxTime) || new Date(parsedTime.getTime()).setFullYear(1970, 0, 1) <= options.maxTime;\n var isValid = isMinValid && isMaxValid;\n controller.$setValidity('date', isValid);\n controller.$setValidity('min', isMinValid);\n controller.$setValidity('max', isMaxValid);\n // Only update the model when we have a valid date\n if(!isValid) {\n return;\n }\n controller.$dateValue = parsedTime;\n }\n\n // viewValue -> $parsers -> modelValue\n controller.$parsers.unshift(function(viewValue) {\n // console.warn('$parser(\"%s\"): viewValue=%o', element.attr('ng-model'), viewValue);\n var date;\n // Null values should correctly reset the model value & validity\n if(!viewValue) {\n // BREAKING CHANGE:\n // return null (not undefined) when input value is empty, so angularjs 1.3\n // ngModelController can go ahead and run validators, like ngRequired\n controller.$setValidity('date', true);\n return null;\n }\n var parsedTime = angular.isDate(viewValue) ? viewValue : dateParser.parse(viewValue, controller.$dateValue);\n if(!parsedTime || isNaN(parsedTime.getTime())) {\n controller.$setValidity('date', false);\n // return undefined, causes ngModelController to\n // invalidate model value\n return;\n } else {\n validateAgainstMinMaxTime(parsedTime);\n }\n\n if(options.timeType === 'string') {\n date = dateParser.timezoneOffsetAdjust(parsedTime, options.timezone, true);\n return formatDate(date, options.modelTimeFormat || options.timeFormat);\n }\n date = dateParser.timezoneOffsetAdjust(controller.$dateValue, options.timezone, true);\n if(options.timeType === 'number') {\n return date.getTime();\n } else if(options.timeType === 'unix') {\n return date.getTime() / 1000;\n } else if(options.timeType === 'iso') {\n return date.toISOString();\n } else {\n return new Date(date);\n }\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var date;\n if(angular.isUndefined(modelValue) || modelValue === null) {\n date = NaN;\n } else if(angular.isDate(modelValue)) {\n date = modelValue;\n } else if(options.timeType === 'string') {\n date = dateParser.parse(modelValue, null, options.modelTimeFormat);\n } else if(options.timeType === 'unix') {\n date = new Date(modelValue * 1000);\n } else {\n date = new Date(modelValue);\n }\n // Setup default value?\n // if(isNaN(date.getTime())) date = new Date(new Date().setMinutes(0) + 36e5);\n controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n return getTimeFormattedString();\n });\n\n // viewValue -> element\n controller.$render = function() {\n // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n element.val(getTimeFormattedString());\n };\n\n function getTimeFormattedString() {\n return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.timeFormat);\n }\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (timepicker) timepicker.destroy();\n options = null;\n timepicker = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.helpers.dimensions'])\n\n .provider('$tooltip', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n customClass: '',\n prefixClass: 'tooltip',\n prefixEvent: 'tooltip',\n container: false,\n target: false,\n placement: 'top',\n template: 'tooltip/tooltip.tpl.html',\n contentTemplate: false,\n trigger: 'hover focus',\n keyboard: false,\n html: false,\n show: false,\n title: '',\n type: '',\n delay: 0,\n autoClose: false,\n bsEnabled: true,\n viewport: {\n selector: 'body',\n padding: 0\n }\n };\n\n this.$get = function($window, $rootScope, $compile, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n var trim = String.prototype.trim;\n var isTouch = 'createTouch' in $window.document;\n var htmlReplaceRegExp = /ng-bind=\"/ig;\n var $body = angular.element($window.document);\n\n function TooltipFactory(element, config) {\n\n var $tooltip = {};\n\n // Common vars\n var nodeName = element[0].nodeName.toLowerCase();\n var options = $tooltip.$options = angular.extend({}, defaults, config);\n $tooltip.$promise = fetchTemplate(options.template);\n var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n if(options.delay && angular.isString(options.delay)) {\n var split = options.delay.split(',').map(parseFloat);\n options.delay = split.length > 1 ? {show: split[0], hide: split[1]} : split[0];\n }\n\n // store $id to identify the triggering element in events\n // give priority to options.id, otherwise, try to use\n // element id if defined\n $tooltip.$id = options.id || element.attr('id') || '';\n\n // Support scope as string options\n if(options.title) {\n scope.title = $sce.trustAsHtml(options.title);\n }\n\n // Provide scope helpers\n scope.$setEnabled = function(isEnabled) {\n scope.$$postDigest(function() {\n $tooltip.setEnabled(isEnabled);\n });\n };\n scope.$hide = function() {\n scope.$$postDigest(function() {\n $tooltip.hide();\n });\n };\n scope.$show = function() {\n scope.$$postDigest(function() {\n $tooltip.show();\n });\n };\n scope.$toggle = function() {\n scope.$$postDigest(function() {\n $tooltip.toggle();\n });\n };\n // Publish isShown as a protected var on scope\n $tooltip.$isShown = scope.$isShown = false;\n\n // Private vars\n var timeout, hoverState;\n\n // Support contentTemplate option\n if(options.contentTemplate) {\n $tooltip.$promise = $tooltip.$promise.then(function(template) {\n var templateEl = angular.element(template);\n return fetchTemplate(options.contentTemplate)\n .then(function(contentTemplate) {\n var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0]);\n if(!contentEl.length) contentEl = findElement('[ng-bind=\"title\"]', templateEl[0]);\n contentEl.removeAttr('ng-bind').html(contentTemplate);\n return templateEl[0].outerHTML;\n });\n });\n }\n\n // Fetch, compile then initialize tooltip\n var tipLinker, tipElement, tipTemplate, tipContainer, tipScope;\n $tooltip.$promise.then(function(template) {\n if(angular.isObject(template)) template = template.data;\n if(options.html) template = template.replace(htmlReplaceRegExp, 'ng-bind-html=\"');\n template = trim.apply(template);\n tipTemplate = template;\n tipLinker = $compile(template);\n $tooltip.init();\n });\n\n $tooltip.init = function() {\n\n // Options: delay\n if (options.delay && angular.isNumber(options.delay)) {\n options.delay = {\n show: options.delay,\n hide: options.delay\n };\n }\n\n // Replace trigger on touch devices ?\n // if(isTouch && options.trigger === defaults.trigger) {\n // options.trigger.replace(/hover/g, 'click');\n // }\n\n // Options : container\n if(options.container === 'self') {\n tipContainer = element;\n } else if(angular.isElement(options.container)) {\n tipContainer = options.container;\n } else if(options.container) {\n tipContainer = findElement(options.container);\n }\n\n // Options: trigger\n bindTriggerEvents();\n\n // Options: target\n if(options.target) {\n options.target = angular.isElement(options.target) ? options.target : findElement(options.target);\n }\n\n // Options: show\n if(options.show) {\n scope.$$postDigest(function() {\n options.trigger === 'focus' ? element[0].focus() : $tooltip.show();\n });\n }\n\n };\n\n $tooltip.destroy = function() {\n\n // Unbind events\n unbindTriggerEvents();\n\n // Remove element\n destroyTipElement();\n\n // Destroy scope\n scope.$destroy();\n\n };\n\n $tooltip.enter = function() {\n\n clearTimeout(timeout);\n hoverState = 'in';\n if (!options.delay || !options.delay.show) {\n return $tooltip.show();\n }\n\n timeout = setTimeout(function() {\n if (hoverState ==='in') $tooltip.show();\n }, options.delay.show);\n\n };\n\n $tooltip.show = function() {\n if (!options.bsEnabled || $tooltip.$isShown) return;\n\n scope.$emit(options.prefixEvent + '.show.before', $tooltip);\n var parent, after;\n if (options.container) {\n parent = tipContainer;\n if (tipContainer[0].lastChild) {\n after = angular.element(tipContainer[0].lastChild);\n } else {\n after = null;\n }\n } else {\n parent = null;\n after = element;\n }\n\n\n // Hide any existing tipElement\n if(tipElement) destroyTipElement();\n // Fetch a cloned element linked from template\n tipScope = $tooltip.$scope.$new();\n tipElement = $tooltip.$element = tipLinker(tipScope, function(clonedElement, scope) {});\n\n // Set the initial positioning. Make the tooltip invisible\n // so IE doesn't try to focus on it off screen.\n tipElement.css({top: '-9999px', left: '-9999px', right: 'auto', display: 'block', visibility: 'hidden'});\n\n // Options: animation\n if(options.animation) tipElement.addClass(options.animation);\n // Options: type\n if(options.type) tipElement.addClass(options.prefixClass + '-' + options.type);\n // Options: custom classes\n if(options.customClass) tipElement.addClass(options.customClass);\n\n // Append the element, without any animations. If we append\n // using $animate.enter, some of the animations cause the placement\n // to be off due to the transforms.\n after ? after.after(tipElement) : parent.prepend(tipElement);\n\n $tooltip.$isShown = scope.$isShown = true;\n safeDigest(scope);\n\n // Now, apply placement\n $tooltip.$applyPlacement();\n\n // Once placed, animate it.\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.enter(tipElement, parent, after, enterAnimateCallback);\n if(promise && promise.then) promise.then(enterAnimateCallback);\n safeDigest(scope);\n\n $$rAF(function () {\n // Once the tooltip is placed and the animation starts, make the tooltip visible\n if(tipElement) tipElement.css({visibility: 'visible'});\n });\n\n // Bind events\n if(options.keyboard) {\n if(options.trigger !== 'focus') {\n $tooltip.focus();\n }\n bindKeyboardEvents();\n }\n\n if(options.autoClose) {\n bindAutoCloseEvents();\n }\n\n };\n\n function enterAnimateCallback() {\n scope.$emit(options.prefixEvent + '.show', $tooltip);\n }\n\n $tooltip.leave = function() {\n\n clearTimeout(timeout);\n hoverState = 'out';\n if (!options.delay || !options.delay.hide) {\n return $tooltip.hide();\n }\n timeout = setTimeout(function () {\n if (hoverState === 'out') {\n $tooltip.hide();\n }\n }, options.delay.hide);\n\n };\n\n var _blur;\n var _tipToHide;\n $tooltip.hide = function(blur) {\n\n if(!$tooltip.$isShown) return;\n scope.$emit(options.prefixEvent + '.hide.before', $tooltip);\n\n // store blur value for leaveAnimateCallback to use\n _blur = blur;\n\n // store current tipElement reference to use\n // in leaveAnimateCallback\n _tipToHide = tipElement;\n\n // Support v1.3+ $animate\n // https://github.com/angular/angular.js/commit/bf0f5502b1bbfddc5cdd2f138efd9188b8c652a9\n var promise = $animate.leave(tipElement, leaveAnimateCallback);\n if(promise && promise.then) promise.then(leaveAnimateCallback);\n\n $tooltip.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if(options.keyboard && tipElement !== null) {\n unbindKeyboardEvents();\n }\n\n if(options.autoClose && tipElement !== null) {\n unbindAutoCloseEvents();\n }\n };\n\n function leaveAnimateCallback() {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\n\n // check if current tipElement still references\n // the same element when hide was called\n if (tipElement === _tipToHide) {\n // Allow to blur the input when hidden, like when pressing enter key\n if(_blur && options.trigger === 'focus') {\n return element[0].blur();\n }\n\n // clean up child scopes\n destroyTipElement();\n }\n }\n\n $tooltip.toggle = function() {\n $tooltip.$isShown ? $tooltip.leave() : $tooltip.enter();\n };\n\n $tooltip.focus = function() {\n tipElement[0].focus();\n };\n\n $tooltip.setEnabled = function(isEnabled) {\n options.bsEnabled = isEnabled;\n };\n\n $tooltip.setViewport = function(viewport) {\n options.viewport = viewport;\n };\n\n // Protected methods\n\n $tooltip.$applyPlacement = function() {\n if(!tipElement) return;\n\n // Determine if we're doing an auto or normal placement\n var placement = options.placement,\n autoToken = /\\s?auto?\\s?/i,\n autoPlace = autoToken.test(placement);\n\n if (autoPlace) {\n placement = placement.replace(autoToken, '') || defaults.placement;\n }\n\n // Need to add the position class before we get\n // the offsets\n tipElement.addClass(options.placement);\n\n // Get the position of the target element\n // and the height and width of the tooltip so we can center it.\n var elementPosition = getPosition(),\n tipWidth = tipElement.prop('offsetWidth'),\n tipHeight = tipElement.prop('offsetHeight');\n\n // If we're auto placing, we need to check the positioning\n if (autoPlace) {\n var originalPlacement = placement;\n var container = options.container ? findElement(options.container) : element.parent();\n var containerPosition = getPosition(container);\n\n // Determine if the vertical placement\n if (originalPlacement.indexOf('bottom') >= 0 && elementPosition.bottom + tipHeight > containerPosition.bottom) {\n placement = originalPlacement.replace('bottom', 'top');\n } else if (originalPlacement.indexOf('top') >= 0 && elementPosition.top - tipHeight < containerPosition.top) {\n placement = originalPlacement.replace('top', 'bottom');\n }\n\n // Determine the horizontal placement\n // The exotic placements of left and right are opposite of the standard placements. Their arrows are put on the left/right\n // and flow in the opposite direction of their placement.\n if ((originalPlacement === 'right' || originalPlacement === 'bottom-left' || originalPlacement === 'top-left') &&\n elementPosition.right + tipWidth > containerPosition.width) {\n\n placement = originalPlacement === 'right' ? 'left' : placement.replace('left', 'right');\n } else if ((originalPlacement === 'left' || originalPlacement === 'bottom-right' || originalPlacement === 'top-right') &&\n elementPosition.left - tipWidth < containerPosition.left) {\n\n placement = originalPlacement === 'left' ? 'right' : placement.replace('right', 'left');\n }\n\n tipElement.removeClass(originalPlacement).addClass(placement);\n }\n\n // Get the tooltip's top and left coordinates to center it with this directive.\n var tipPosition = getCalculatedOffset(placement, elementPosition, tipWidth, tipHeight);\n applyPlacement(tipPosition, placement);\n };\n\n $tooltip.$onKeyUp = function(evt) {\n if (evt.which === 27 && $tooltip.$isShown) {\n $tooltip.hide();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusKeyUp = function(evt) {\n if (evt.which === 27) {\n element[0].blur();\n evt.stopPropagation();\n }\n };\n\n $tooltip.$onFocusElementMouseDown = function(evt) {\n evt.preventDefault();\n evt.stopPropagation();\n // Some browsers do not auto-focus buttons (eg. Safari)\n $tooltip.$isShown ? element[0].blur() : element[0].focus();\n };\n\n // bind/unbind events\n function bindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n angular.forEach(triggers, function(trigger) {\n if(trigger === 'click') {\n element.on('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.on(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.on(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n });\n }\n\n function unbindTriggerEvents() {\n var triggers = options.trigger.split(' ');\n for (var i = triggers.length; i--;) {\n var trigger = triggers[i];\n if(trigger === 'click') {\n element.off('click', $tooltip.toggle);\n } else if(trigger !== 'manual') {\n element.off(trigger === 'hover' ? 'mouseenter' : 'focus', $tooltip.enter);\n element.off(trigger === 'hover' ? 'mouseleave' : 'blur', $tooltip.leave);\n nodeName === 'button' && trigger !== 'hover' && element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n }\n }\n }\n\n function bindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.on('keyup', $tooltip.$onKeyUp);\n } else {\n element.on('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n function unbindKeyboardEvents() {\n if(options.trigger !== 'focus') {\n tipElement.off('keyup', $tooltip.$onKeyUp);\n } else {\n element.off('keyup', $tooltip.$onFocusKeyUp);\n }\n }\n\n var _autoCloseEventsBinded = false;\n function bindAutoCloseEvents() {\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n // Stop propagation when clicking inside tooltip\n tipElement.on('click', stopEventPropagation);\n\n // Hide when clicking outside tooltip\n $body.on('click', $tooltip.hide);\n\n _autoCloseEventsBinded = true;\n }, 0, false);\n }\n\n function unbindAutoCloseEvents() {\n if (_autoCloseEventsBinded) {\n tipElement.off('click', stopEventPropagation);\n $body.off('click', $tooltip.hide);\n _autoCloseEventsBinded = false;\n }\n }\n\n function stopEventPropagation(event) {\n event.stopPropagation();\n }\n\n // Private methods\n\n function getPosition($element) {\n $element = $element || (options.target || element);\n\n var el = $element[0],\n isBody = el.tagName === 'BODY';\n\n var elRect = el.getBoundingClientRect();\n var rect = {};\n\n // IE8 has issues with angular.extend and using elRect directly.\n // By coping the values of elRect into a new object, we can continue to use extend\n for (var p in elRect) {\n // DO NOT use hasOwnProperty when inspecting the return of getBoundingClientRect.\n rect[p] = elRect[p];\n }\n\n if (rect.width === null) {\n // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n rect = angular.extend({}, rect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top });\n }\n var elOffset = isBody ? { top: 0, left: 0 } : dimensions.offset(el),\n scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.prop('scrollTop') || 0 },\n outerDims = isBody ? { width: document.documentElement.clientWidth, height: $window.innerHeight } : null;\n\n return angular.extend({}, rect, scroll, outerDims, elOffset);\n }\n\n function getCalculatedOffset(placement, position, actualWidth, actualHeight) {\n var offset;\n var split = placement.split('-');\n\n switch (split[0]) {\n case 'right':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left + position.width\n };\n break;\n case 'bottom':\n offset = {\n top: position.top + position.height,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n case 'left':\n offset = {\n top: position.top + position.height / 2 - actualHeight / 2,\n left: position.left - actualWidth\n };\n break;\n default:\n offset = {\n top: position.top - actualHeight,\n left: position.left + position.width / 2 - actualWidth / 2\n };\n break;\n }\n\n if(!split[1]) {\n return offset;\n }\n\n // Add support for corners @todo css\n if(split[0] === 'top' || split[0] === 'bottom') {\n switch (split[1]) {\n case 'left':\n offset.left = position.left;\n break;\n case 'right':\n offset.left = position.left + position.width - actualWidth;\n }\n } else if(split[0] === 'left' || split[0] === 'right') {\n switch (split[1]) {\n case 'top':\n offset.top = position.top - actualHeight;\n break;\n case 'bottom':\n offset.top = position.top + position.height;\n }\n }\n\n return offset;\n }\n\n function applyPlacement(offset, placement) {\n var tip = tipElement[0],\n width = tip.offsetWidth,\n height = tip.offsetHeight;\n\n // manually read margins because getBoundingClientRect includes difference\n var marginTop = parseInt(dimensions.css(tip, 'margin-top'), 10),\n marginLeft = parseInt(dimensions.css(tip, 'margin-left'), 10);\n\n // we must check for NaN for ie 8/9\n if (isNaN(marginTop)) marginTop = 0;\n if (isNaN(marginLeft)) marginLeft = 0;\n\n offset.top = offset.top + marginTop;\n offset.left = offset.left + marginLeft;\n\n // dimensions setOffset doesn't round pixel values\n // so we use setOffset directly with our own function\n dimensions.setOffset(tip, angular.extend({\n using: function (props) {\n tipElement.css({\n top: Math.round(props.top) + 'px',\n left: Math.round(props.left) + 'px',\n right: ''\n });\n }\n }, offset), 0);\n\n // check to see if placing tip in new offset caused the tip to resize itself\n var actualWidth = tip.offsetWidth,\n actualHeight = tip.offsetHeight;\n\n if (placement === 'top' && actualHeight !== height) {\n offset.top = offset.top + height - actualHeight;\n }\n\n // If it's an exotic placement, exit now instead of\n // applying a delta and changing the arrow\n if (/top-left|top-right|bottom-left|bottom-right/.test(placement)) return;\n\n var delta = getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);\n\n if (delta.left) {\n offset.left += delta.left;\n } else {\n offset.top += delta.top;\n }\n\n dimensions.setOffset(tip, offset);\n\n if (/top|right|bottom|left/.test(placement)) {\n var isVertical = /top|bottom/.test(placement),\n arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight,\n arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';\n\n replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical);\n }\n }\n\n function getViewportAdjustedDelta(placement, position, actualWidth, actualHeight) {\n var delta = { top: 0, left: 0 },\n $viewport = options.viewport && findElement(options.viewport.selector || options.viewport);\n\n if (!$viewport) {\n return delta;\n }\n\n var viewportPadding = options.viewport && options.viewport.padding || 0,\n viewportDimensions = getPosition($viewport);\n\n if (/right|left/.test(placement)) {\n var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll,\n bottomEdgeOffset = position.top + viewportPadding - viewportDimensions.scroll + actualHeight;\n if (topEdgeOffset < viewportDimensions.top) { // top overflow\n delta.top = viewportDimensions.top - topEdgeOffset;\n } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;\n }\n } else {\n var leftEdgeOffset = position.left - viewportPadding,\n rightEdgeOffset = position.left + viewportPadding + actualWidth;\n if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n delta.left = viewportDimensions.left - leftEdgeOffset;\n } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow\n delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;\n }\n }\n\n return delta;\n }\n\n function replaceArrow(delta, dimension, isHorizontal) {\n var $arrow = findElement('.tooltip-arrow, .arrow', tipElement[0]);\n\n $arrow.css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')\n .css(isHorizontal ? 'top' : 'left', '');\n }\n\n function destroyTipElement() {\n // Cancel pending callbacks\n clearTimeout(timeout);\n\n if($tooltip.$isShown && tipElement !== null) {\n if(options.autoClose) {\n unbindAutoCloseEvents();\n }\n\n if(options.keyboard) {\n unbindKeyboardEvents();\n }\n }\n\n if(tipScope) {\n tipScope.$destroy();\n tipScope = null;\n }\n\n if(tipElement) {\n tipElement.remove();\n tipElement = $tooltip.$element = null;\n }\n }\n\n return $tooltip;\n\n }\n\n // Helper functions\n\n function safeDigest(scope) {\n scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n }\n\n function findElement(query, element) {\n return angular.element((element || document).querySelectorAll(query));\n }\n\n var fetchPromises = {};\n function fetchTemplate(template) {\n if(fetchPromises[template]) return fetchPromises[template];\n return (fetchPromises[template] = $http.get(template, {cache: $templateCache}).then(function(res) {\n return res.data;\n }));\n }\n\n return TooltipFactory;\n\n };\n\n })\n\n .directive('bsTooltip', function($window, $location, $sce, $tooltip, $$rAF) {\n\n return {\n restrict: 'EAC',\n scope: true,\n link: function postLink(scope, element, attr, transclusion) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'backdropAnimation', 'type', 'customClass', 'id'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key]))\n options[key] = false;\n });\n\n // should not parse target attribute (anchor tag), only data-target #1454\n var dataTarget = element.attr('data-target');\n if(angular.isDefined(dataTarget)) {\n if(falseValueRegExp.test(dataTarget))\n options.target = false;\n else\n options.target = dataTarget;\n }\n\n // overwrite inherited title value when no value specified\n // fix for angular 1.3.1 531a8de72c439d8ddd064874bf364c00cedabb11\n if (!scope.hasOwnProperty('title')){\n scope.title = '';\n }\n\n // Observe scope attributes for change\n attr.$observe('title', function(newValue) {\n if (angular.isDefined(newValue) || !scope.hasOwnProperty('title')) {\n var oldValue = scope.title;\n scope.title = $sce.trustAsHtml(newValue);\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }\n });\n\n // Support scope as an object\n attr.bsTooltip && scope.$watch(attr.bsTooltip, function(newValue, oldValue) {\n if(angular.isObject(newValue)) {\n angular.extend(scope, newValue);\n } else {\n scope.title = newValue;\n }\n angular.isDefined(oldValue) && $$rAF(function() {\n tooltip && tooltip.$applyPlacement();\n });\n }, true);\n\n // Visibility binding support\n attr.bsShow && scope.$watch(attr.bsShow, function(newValue, oldValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|,?(tooltip),?/i);\n newValue === true ? tooltip.show() : tooltip.hide();\n });\n\n // Enabled binding support\n attr.bsEnabled && scope.$watch(attr.bsEnabled, function(newValue, oldValue) {\n // console.warn('scope.$watch(%s)', attr.bsEnabled, newValue, oldValue);\n if(!tooltip || !angular.isDefined(newValue)) return;\n if(angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(tooltip),?/i);\n newValue === false ? tooltip.setEnabled(false) : tooltip.setEnabled(true);\n });\n\n // Viewport support\n attr.viewport && scope.$watch(attr.viewport, function (newValue) {\n if(!tooltip || !angular.isDefined(newValue)) return;\n tooltip.setViewport(newValue);\n });\n\n // Initialize popover\n var tooltip = $tooltip(element, options);\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if(tooltip) tooltip.destroy();\n options = null;\n tooltip = null;\n });\n\n }\n };\n\n });\n","'use strict';\n\nangular.module('mgcrea.ngStrap.typeahead', ['mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions'])\n\n .provider('$typeahead', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n prefixClass: 'typeahead',\n prefixEvent: '$typeahead',\n placement: 'bottom-left',\n template: 'typeahead/typeahead.tpl.html',\n trigger: 'focus',\n container: false,\n keyboard: true,\n html: false,\n delay: 0,\n minLength: 1,\n filter: 'filter',\n limit: 6,\n autoSelect: false,\n comparator: '',\n trimValue: true\n };\n\n this.$get = function($window, $rootScope, $tooltip, $timeout) {\n\n var bodyEl = angular.element($window.document.body);\n\n function TypeaheadFactory(element, controller, config) {\n\n var $typeahead = {};\n\n // Common vars\n var options = angular.extend({}, defaults, config);\n\n $typeahead = $tooltip(element, options);\n var parentScope = config.scope;\n var scope = $typeahead.$scope;\n\n scope.$resetMatches = function(){\n scope.$matches = [];\n scope.$activeIndex = options.autoSelect ? 0 : -1; // If set to 0, the first match will be highlighted\n };\n scope.$resetMatches();\n\n scope.$activate = function(index) {\n scope.$$postDigest(function() {\n $typeahead.activate(index);\n });\n };\n\n scope.$select = function(index, evt) {\n scope.$$postDigest(function() {\n $typeahead.select(index);\n });\n };\n\n scope.$isVisible = function() {\n return $typeahead.$isVisible();\n };\n\n // Public methods\n\n $typeahead.update = function(matches) {\n scope.$matches = matches;\n if(scope.$activeIndex >= matches.length) {\n scope.$activeIndex = options.autoSelect ? 0: -1;\n }\n\n // When the placement is not one of the bottom placements, re-calc the positioning\n // so the results render correctly.\n if (/^(bottom|bottom-left|bottom-right)$/.test(options.placement)) return;\n\n // wrap in a $timeout so the results are updated\n // before repositioning\n $timeout($typeahead.$applyPlacement);\n };\n\n $typeahead.activate = function(index) {\n scope.$activeIndex = index;\n };\n\n $typeahead.select = function(index) {\n if(index === -1) return;\n var value = scope.$matches[index].value;\n // console.log('$setViewValue', value);\n controller.$setViewValue(value);\n controller.$render();\n scope.$resetMatches();\n if(parentScope) parentScope.$digest();\n // Emit event\n scope.$emit(options.prefixEvent + '.select', value, index, $typeahead);\n };\n\n // Protected methods\n\n $typeahead.$isVisible = function() {\n if(!options.minLength || !controller) {\n return !!scope.$matches.length;\n }\n // minLength support\n return scope.$matches.length && angular.isString(controller.$viewValue) && controller.$viewValue.length >= options.minLength;\n };\n\n $typeahead.$getIndex = function(value) {\n var l = scope.$matches.length, i = l;\n if(!l) return;\n for(i = l; i--;) {\n if(scope.$matches[i].value === value) break;\n }\n if(i < 0) return;\n return i;\n };\n\n $typeahead.$onMouseDown = function(evt) {\n // Prevent blur on mousedown\n evt.preventDefault();\n evt.stopPropagation();\n };\n\n $typeahead.$onKeyDown = function(evt) {\n if(!/(38|40|13)/.test(evt.keyCode)) return;\n\n // Let ngSubmit pass if the typeahead tip is hidden or no option is selected\n if($typeahead.$isVisible() && !(evt.keyCode === 13 && scope.$activeIndex === -1)) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n\n // Select with enter\n if(evt.keyCode === 13 && scope.$matches.length) {\n $typeahead.select(scope.$activeIndex);\n }\n\n // Navigate with keyboard\n else if(evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--;\n else if(evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++;\n else if(angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;\n scope.$digest();\n };\n\n // Overrides\n\n var show = $typeahead.show;\n $typeahead.show = function() {\n show();\n // use timeout to hookup the events to prevent\n // event bubbling from being processed imediately.\n $timeout(function() {\n $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.on('keydown', $typeahead.$onKeyDown);\n }\n }, 0, false);\n };\n\n var hide = $typeahead.hide;\n $typeahead.hide = function() {\n $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n if(options.keyboard) {\n element.off('keydown', $typeahead.$onKeyDown);\n }\n if(!options.autoSelect)\n $typeahead.activate(-1);\n hide();\n };\n\n return $typeahead;\n\n }\n\n TypeaheadFactory.defaults = defaults;\n return TypeaheadFactory;\n\n };\n\n })\n\n .directive('bsTypeahead', function($window, $parse, $q, $typeahead, $parseOptions) {\n\n var defaults = $typeahead.defaults;\n\n return {\n restrict: 'EAC',\n require: 'ngModel',\n link: function postLink(scope, element, attr, controller) {\n\n // Directive options\n var options = {scope: scope};\n angular.forEach(['placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'template', 'filter', 'limit', 'minLength', 'watchOptions', 'selectMode', 'autoSelect', 'comparator', 'id', 'prefixEvent', 'prefixClass'], function(key) {\n if(angular.isDefined(attr[key])) options[key] = attr[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['html', 'container', 'trimValue'], function(key) {\n if(angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n });\n\n // Disable browser autocompletion\n element.attr('autocomplete' ,'off');\n\n // Build proper bsOptions\n var filter = options.filter || defaults.filter;\n var limit = options.limit || defaults.limit;\n var comparator = options.comparator || defaults.comparator;\n\n var bsOptions = attr.bsOptions;\n if(filter) bsOptions += ' | ' + filter + ':$viewValue';\n if (comparator) bsOptions += ':' + comparator;\n if(limit) bsOptions += ' | limitTo:' + limit;\n var parsedOptions = $parseOptions(bsOptions);\n\n // Initialize typeahead\n var typeahead = $typeahead(element, controller, options);\n\n // Watch options on demand\n if(options.watchOptions) {\n // Watch bsOptions values before filtering for changes, drop function calls\n var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').replace(/\\(.*\\)/g, '').trim();\n scope.$watchCollection(watchedOptions, function (newValue, oldValue) {\n // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n parsedOptions.valuesFn(scope, controller).then(function (values) {\n typeahead.update(values);\n controller.$render();\n });\n });\n }\n\n // Watch model for changes\n scope.$watch(attr.ngModel, function(newValue, oldValue) {\n // console.warn('$watch', element.attr('ng-model'), newValue);\n scope.$modelValue = newValue; // Publish modelValue on scope for custom templates\n parsedOptions.valuesFn(scope, controller)\n .then(function(values) {\n // Prevent input with no future prospect if selectMode is truthy\n // @TODO test selectMode\n if(options.selectMode && !values.length && newValue.length > 0) {\n controller.$setViewValue(controller.$viewValue.substring(0, controller.$viewValue.length - 1));\n return;\n }\n if(values.length > limit) values = values.slice(0, limit);\n var isVisible = typeahead.$isVisible();\n isVisible && typeahead.update(values);\n // Do not re-queue an update if a correct value has been selected\n if(values.length === 1 && values[0].value === newValue) return;\n !isVisible && typeahead.update(values);\n // Queue a new rendering that will leverage collection loading\n controller.$render();\n });\n });\n\n // modelValue -> $formatters -> viewValue\n controller.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n var displayValue = parsedOptions.displayValue(modelValue);\n return displayValue === undefined ? '' : displayValue;\n });\n\n // Model rendering in view\n controller.$render = function () {\n // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n if(controller.$isEmpty(controller.$viewValue)) return element.val('');\n var index = typeahead.$getIndex(controller.$modelValue);\n var selected = angular.isDefined(index) ? typeahead.$scope.$matches[index].label : controller.$viewValue;\n selected = angular.isObject(selected) ? parsedOptions.displayValue(selected) : selected;\n var value = selected ? selected.toString().replace(/<(?:.|\\n)*?>/gm, '') : '';\n element.val(options.trimValue === false ? value : value.trim());\n };\n\n // Garbage collection\n scope.$on('$destroy', function() {\n if (typeahead) typeahead.destroy();\n options = null;\n typeahead = null;\n });\n\n }\n };\n\n });\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/dist/angular-strap.tpl.js b/dist/angular-strap.tpl.js index 5cf300cac..9322ff30e 100644 --- a/dist/angular-strap.tpl.js +++ b/dist/angular-strap.tpl.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT @@ -28,12 +28,12 @@ angular.module('mgcrea.ngStrap.select').run([ '$templateCache', function($templateCache) { $templateCache.put('select/select.tpl.html', ''); } ]); + angular.module('mgcrea.ngStrap.tab').run([ '$templateCache', function($templateCache) { + $templateCache.put('tab/tab.tpl.html', '
'); + } ]); angular.module('mgcrea.ngStrap.timepicker').run([ '$templateCache', function($templateCache) { $templateCache.put('timepicker/timepicker.tpl.html', ''); } ]); - angular.module('mgcrea.ngStrap.tab').run([ '$templateCache', function($templateCache) { - $templateCache.put('tab/tab.tpl.html', '
'); - } ]); angular.module('mgcrea.ngStrap.tooltip').run([ '$templateCache', function($templateCache) { $templateCache.put('tooltip/tooltip.tpl.html', '
'); } ]); diff --git a/dist/angular-strap.tpl.min.js b/dist/angular-strap.tpl.min.js index 54f1b6b78..24d6894f6 100644 --- a/dist/angular-strap.tpl.min.js +++ b/dist/angular-strap.tpl.min.js @@ -1,8 +1,8 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT */ -!function(t,e,n){'use strict';angular.module('mgcrea.ngStrap.alert').run(['$templateCache',function(t){t.put('alert/alert.tpl.html','
 
')}]),angular.module('mgcrea.ngStrap.aside').run(['$templateCache',function(t){t.put('aside/aside.tpl.html','')}]),angular.module('mgcrea.ngStrap.datepicker').run(['$templateCache',function(t){t.put('datepicker/datepicker.tpl.html','')}]),angular.module('mgcrea.ngStrap.dropdown').run(['$templateCache',function(t){t.put('dropdown/dropdown.tpl.html','')}]),angular.module('mgcrea.ngStrap.modal').run(['$templateCache',function(t){t.put('modal/modal.tpl.html','')}]),angular.module('mgcrea.ngStrap.popover').run(['$templateCache',function(t){t.put('popover/popover.tpl.html','

')}]),angular.module('mgcrea.ngStrap.select').run(['$templateCache',function(t){t.put('select/select.tpl.html','')}]),angular.module('mgcrea.ngStrap.timepicker').run(['$templateCache',function(t){t.put('timepicker/timepicker.tpl.html','')}]),angular.module('mgcrea.ngStrap.tab').run(['$templateCache',function(t){t.put('tab/tab.tpl.html','
')}]),angular.module('mgcrea.ngStrap.tooltip').run(['$templateCache',function(t){t.put('tooltip/tooltip.tpl.html','
')}]),angular.module('mgcrea.ngStrap.typeahead').run(['$templateCache',function(t){t.put('typeahead/typeahead.tpl.html','')}])}(window,document); \ No newline at end of file +!function(t,e,n){'use strict';angular.module('mgcrea.ngStrap.alert').run(['$templateCache',function(t){t.put('alert/alert.tpl.html','
 
')}]),angular.module('mgcrea.ngStrap.aside').run(['$templateCache',function(t){t.put('aside/aside.tpl.html','')}]),angular.module('mgcrea.ngStrap.datepicker').run(['$templateCache',function(t){t.put('datepicker/datepicker.tpl.html','')}]),angular.module('mgcrea.ngStrap.dropdown').run(['$templateCache',function(t){t.put('dropdown/dropdown.tpl.html','')}]),angular.module('mgcrea.ngStrap.modal').run(['$templateCache',function(t){t.put('modal/modal.tpl.html','')}]),angular.module('mgcrea.ngStrap.popover').run(['$templateCache',function(t){t.put('popover/popover.tpl.html','

')}]),angular.module('mgcrea.ngStrap.select').run(['$templateCache',function(t){t.put('select/select.tpl.html','')}]),angular.module('mgcrea.ngStrap.tab').run(['$templateCache',function(t){t.put('tab/tab.tpl.html','
')}]),angular.module('mgcrea.ngStrap.timepicker').run(['$templateCache',function(t){t.put('timepicker/timepicker.tpl.html','')}]),angular.module('mgcrea.ngStrap.tooltip').run(['$templateCache',function(t){t.put('tooltip/tooltip.tpl.html','
')}]),angular.module('mgcrea.ngStrap.typeahead').run(['$templateCache',function(t){t.put('typeahead/typeahead.tpl.html','')}])}(window,document); \ No newline at end of file diff --git a/dist/modules/affix.js b/dist/modules/affix.js index 7ea85ed16..a50c99abb 100644 --- a/dist/modules/affix.js +++ b/dist/modules/affix.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/affix.min.js b/dist/modules/affix.min.js index a0252d456..bcfc9f9eb 100644 --- a/dist/modules/affix.min.js +++ b/dist/modules/affix.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/alert.js b/dist/modules/alert.js index c870571d0..6d17cc44a 100644 --- a/dist/modules/alert.js +++ b/dist/modules/alert.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/alert.min.js b/dist/modules/alert.min.js index cb3298a83..d22c7b4e5 100644 --- a/dist/modules/alert.min.js +++ b/dist/modules/alert.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/alert.tpl.js b/dist/modules/alert.tpl.js index f6a660cf0..f66e6ae8b 100644 --- a/dist/modules/alert.tpl.js +++ b/dist/modules/alert.tpl.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/alert.tpl.min.js b/dist/modules/alert.tpl.min.js index cfb58f935..55d890bc6 100644 --- a/dist/modules/alert.tpl.min.js +++ b/dist/modules/alert.tpl.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/aside.js b/dist/modules/aside.js index d90e6119b..f8de665b6 100644 --- a/dist/modules/aside.js +++ b/dist/modules/aside.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/aside.min.js b/dist/modules/aside.min.js index 156ea0ca6..dd9df3d48 100644 --- a/dist/modules/aside.min.js +++ b/dist/modules/aside.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/aside.tpl.js b/dist/modules/aside.tpl.js index 3002995df..3e12abc70 100644 --- a/dist/modules/aside.tpl.js +++ b/dist/modules/aside.tpl.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/aside.tpl.min.js b/dist/modules/aside.tpl.min.js index ecd9d503d..ab8010aa4 100644 --- a/dist/modules/aside.tpl.min.js +++ b/dist/modules/aside.tpl.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/button.js b/dist/modules/button.js index 2429f7a86..8bb01f626 100644 --- a/dist/modules/button.js +++ b/dist/modules/button.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/button.min.js b/dist/modules/button.min.js index 7d8bee8b0..1a9674941 100644 --- a/dist/modules/button.min.js +++ b/dist/modules/button.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/collapse.js b/dist/modules/collapse.js index ebd7a8d19..516e41432 100644 --- a/dist/modules/collapse.js +++ b/dist/modules/collapse.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT @@ -52,7 +52,7 @@ angular.module('mgcrea.ngStrap.collapse', []).provider('$collapse', function() { self.$targets.$active = !self.$options.startCollapsed ? [ 0 ] : []; self.$setActive = $scope.$setActive = function(value) { if (angular.isArray(value)) { - self.$targets.$active = angular.copy(value); + self.$targets.$active = value; } else if (!self.$options.disallowToggle) { isActive(value) ? deactivateItem(value) : activateItem(value); } else { diff --git a/dist/modules/collapse.min.js b/dist/modules/collapse.min.js index 1ea623f6a..5538e9697 100644 --- a/dist/modules/collapse.min.js +++ b/dist/modules/collapse.min.js @@ -1,9 +1,9 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT */ -'use strict';angular.module('mgcrea.ngStrap.collapse',[]).provider('$collapse',function(){var e=this.defaults={animation:'am-collapse',disallowToggle:!1,activeClass:'in',startCollapsed:!1,allowMultiple:!1},t=this.controller=function(t,a,i){function n(e){for(var t=o.$targets.$active,a=0;a $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n if (angular.isArray(modelValue)) {\n // model value is an array, so just replace\n // the active items directly\n bsCollapseCtrl.$setActive(modelValue);\n }\n else {\n var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n if (angular.isArray(activeIndexes)) {\n // we have an array of selected indexes\n if (activeIndexes.indexOf(modelValue * 1) === -1) {\n // item with modelValue index is not active\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n else if (activeIndexes !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n return modelValue;\n });\n\n }\n\n }\n };\n\n })\n\n .directive('bsCollapseToggle', function() {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base attr\n element.attr('data-toggle', 'collapse');\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerToggle(element);\n\n // remove toggle from collapse controller when toggle is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterToggle(element);\n });\n\n element.on('click', function() {\n var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n bsCollapseCtrl.$setActive(index * 1);\n scope.$apply();\n });\n\n }\n };\n\n })\n\n .directive('bsCollapseTarget', function($animate) {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n // scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base class\n element.addClass('collapse');\n\n // Add animation class\n if(bsCollapseCtrl.$options.animation) {\n element.addClass(bsCollapseCtrl.$options.animation);\n }\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerTarget(element);\n\n // remove pane target from collapse controller when target is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterTarget(element);\n });\n\n function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$activeIndexes();\n var action = 'removeClass';\n if (angular.isArray(active)) {\n if (active.indexOf(index) !== -1) {\n action = 'addClass';\n }\n }\n else if (index === active) {\n action = 'addClass';\n }\n\n $animate[action](element, bsCollapseCtrl.$options.activeClass);\n }\n\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["modules/collapse.js"],"names":["angular","module","provider","controller","this","animation","self","forEach","startCollapsed","isDefined","allowMultiple","$scope","$element","$attrs","activeIndexes","$targets","$active","i","length","index","value","indexOf","activeItems","splice","activateItem","$options","$get","defaults","$collapse","copy","$toggles","push","element","key","falseValueRegExp","test","$unregisterToggle","$registerToggle","$unregisterTarget","deactivateItem","$viewChangeListeners","fn","fixActiveItemIndexes","$setActive","disallowToggle","isActive","$activeIndexes","link","require","directive","bsCollapseCtrl","controllers","$window","$animate","ngModelCtrl","$setViewValue","$formatters","attrs","modelValue","isArray","scope","bsCollapseToggle","$apply","$on","on","$registerTarget","render","active","action","activeClass","addClass"],"mappings":"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","file":"modules/collapse.min.js","sourcesContent":["'use strict';\n\nangular.module('mgcrea.ngStrap.collapse', [])\n\n .provider('$collapse', function() {\n\n var defaults = this.defaults = {\n animation: 'am-collapse',\n disallowToggle: false,\n activeClass: 'in',\n startCollapsed: false,\n allowMultiple: false\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'disallowToggle', 'activeClass', 'startCollapsed', 'allowMultiple'], function (key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // use string regex match boolean attr falsy values, leave truthy values be\n var falseValueRegExp = /^(false|0|)$/i;\n angular.forEach(['disallowToggle', 'startCollapsed', 'allowMultiple'], function(key) {\n if(angular.isDefined($attrs[key]) && falseValueRegExp.test($attrs[key]))\n self.$options[key] = false;\n });\n\n self.$toggles = [];\n self.$targets = [];\n\n self.$viewChangeListeners = [];\n\n self.$registerToggle = function(element) {\n self.$toggles.push(element);\n };\n self.$registerTarget = function(element) {\n self.$targets.push(element);\n };\n\n self.$unregisterToggle = function(element) {\n var index = self.$toggles.indexOf(element);\n // remove toggle from $toggles array\n self.$toggles.splice(index, 1);\n };\n self.$unregisterTarget = function(element) {\n var index = self.$targets.indexOf(element);\n\n // remove element from $targets array\n self.$targets.splice(index, 1);\n\n if (self.$options.allowMultiple) {\n // remove target index from $active array values\n deactivateItem(element);\n }\n\n // fix active item indexes\n fixActiveItemIndexes(index);\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n // use array to store all the currently open panels\n self.$targets.$active = !self.$options.startCollapsed ? [0] : [];\n self.$setActive = $scope.$setActive = function(value) {\n if(angular.isArray(value)) {\n self.$targets.$active = value;\n }\n else if(!self.$options.disallowToggle) {\n // toogle element active status\n isActive(value) ? deactivateItem(value) : activateItem(value);\n } else {\n activateItem(value);\n }\n\n self.$viewChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$activeIndexes = function() {\n return self.$options.allowMultiple ? self.$targets.$active :\n self.$targets.$active.length === 1 ? self.$targets.$active[0] : -1;\n };\n\n function fixActiveItemIndexes(index) {\n // item with index was removed, so we\n // need to adjust other items index values\n var activeIndexes = self.$targets.$active;\n for(var i = 0; i < activeIndexes.length; i++) {\n if (index < activeIndexes[i]) {\n activeIndexes[i] = activeIndexes[i] - 1;\n }\n\n // the last item is active, so we need to\n // adjust its index\n if (activeIndexes[i] === self.$targets.length) {\n activeIndexes[i] = self.$targets.length - 1;\n }\n }\n }\n\n function isActive(value) {\n var activeItems = self.$targets.$active;\n return activeItems.indexOf(value) === -1 ? false : true;\n }\n\n function deactivateItem(value) {\n var index = self.$targets.$active.indexOf(value);\n if (index !== -1) {\n self.$targets.$active.splice(index, 1);\n }\n }\n\n function activateItem(value) {\n if (!self.$options.allowMultiple) {\n // remove current selected item\n self.$targets.$active.splice(0, 1);\n }\n\n if (self.$targets.$active.indexOf(value) === -1) {\n self.$targets.$active.push(value);\n }\n }\n\n };\n\n this.$get = function() {\n var $collapse = {};\n $collapse.defaults = defaults;\n $collapse.controller = controller;\n return $collapse;\n };\n\n })\n\n .directive('bsCollapse', function($window, $animate, $collapse) {\n\n var defaults = $collapse.defaults;\n\n return {\n require: ['?ngModel', 'bsCollapse'],\n controller: ['$scope', '$element', '$attrs', $collapse.controller],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsCollapseCtrl.$activeIndexes());\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n if (angular.isArray(modelValue)) {\n // model value is an array, so just replace\n // the active items directly\n bsCollapseCtrl.$setActive(modelValue);\n }\n else {\n var activeIndexes = bsCollapseCtrl.$activeIndexes();\n\n if (angular.isArray(activeIndexes)) {\n // we have an array of selected indexes\n if (activeIndexes.indexOf(modelValue * 1) === -1) {\n // item with modelValue index is not active\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n else if (activeIndexes !== modelValue * 1) {\n bsCollapseCtrl.$setActive(modelValue * 1);\n }\n }\n return modelValue;\n });\n\n }\n\n }\n };\n\n })\n\n .directive('bsCollapseToggle', function() {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base attr\n element.attr('data-toggle', 'collapse');\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerToggle(element);\n\n // remove toggle from collapse controller when toggle is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterToggle(element);\n });\n\n element.on('click', function() {\n var index = attrs.bsCollapseToggle || bsCollapseCtrl.$toggles.indexOf(element);\n bsCollapseCtrl.$setActive(index * 1);\n scope.$apply();\n });\n\n }\n };\n\n })\n\n .directive('bsCollapseTarget', function($animate) {\n\n return {\n require: ['^?ngModel', '^bsCollapse'],\n // scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsCollapseCtrl = controllers[1];\n\n // Add base class\n element.addClass('collapse');\n\n // Add animation class\n if(bsCollapseCtrl.$options.animation) {\n element.addClass(bsCollapseCtrl.$options.animation);\n }\n\n // Push pane to parent bsCollapse controller\n bsCollapseCtrl.$registerTarget(element);\n\n // remove pane target from collapse controller when target is destroyed\n scope.$on('$destroy', function() {\n bsCollapseCtrl.$unregisterTarget(element);\n });\n\n function render() {\n var index = bsCollapseCtrl.$targets.indexOf(element);\n var active = bsCollapseCtrl.$activeIndexes();\n var action = 'removeClass';\n if (angular.isArray(active)) {\n if (active.indexOf(index) !== -1) {\n action = 'addClass';\n }\n }\n else if (index === active) {\n action = 'addClass';\n }\n\n $animate[action](element, bsCollapseCtrl.$options.activeClass);\n }\n\n bsCollapseCtrl.$viewChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/dist/modules/date-formatter.js b/dist/modules/date-formatter.js index bc86cd667..1a34cba54 100644 --- a/dist/modules/date-formatter.js +++ b/dist/modules/date-formatter.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/date-formatter.min.js b/dist/modules/date-formatter.min.js index 07903bcec..fb6851a66 100644 --- a/dist/modules/date-formatter.min.js +++ b/dist/modules/date-formatter.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/date-parser.js b/dist/modules/date-parser.js index 4de7f3159..7bdaa8412 100644 --- a/dist/modules/date-parser.js +++ b/dist/modules/date-parser.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/date-parser.min.js b/dist/modules/date-parser.min.js index a4859d40b..dc72f00a1 100644 --- a/dist/modules/date-parser.min.js +++ b/dist/modules/date-parser.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/datepicker.js b/dist/modules/datepicker.js index fc83cf204..9ba9b4d59 100644 --- a/dist/modules/datepicker.js +++ b/dist/modules/datepicker.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/datepicker.min.js b/dist/modules/datepicker.min.js index c6545cd29..c902f6148 100644 --- a/dist/modules/datepicker.min.js +++ b/dist/modules/datepicker.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/datepicker.tpl.js b/dist/modules/datepicker.tpl.js index 5d64f6f0a..53093e85a 100644 --- a/dist/modules/datepicker.tpl.js +++ b/dist/modules/datepicker.tpl.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/datepicker.tpl.min.js b/dist/modules/datepicker.tpl.min.js index 0d6d8077b..3dec18465 100644 --- a/dist/modules/datepicker.tpl.min.js +++ b/dist/modules/datepicker.tpl.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/debounce.js b/dist/modules/debounce.js index 2c49e3849..067bf7b18 100644 --- a/dist/modules/debounce.js +++ b/dist/modules/debounce.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/debounce.min.js b/dist/modules/debounce.min.js index bee5a0d5b..7a78b6451 100644 --- a/dist/modules/debounce.min.js +++ b/dist/modules/debounce.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/dimensions.js b/dist/modules/dimensions.js index f9f8ca779..365aeee3d 100644 --- a/dist/modules/dimensions.js +++ b/dist/modules/dimensions.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/dimensions.min.js b/dist/modules/dimensions.min.js index 54f295391..edf58299e 100644 --- a/dist/modules/dimensions.min.js +++ b/dist/modules/dimensions.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/dropdown.js b/dist/modules/dropdown.js index cb961d544..779cc8a80 100644 --- a/dist/modules/dropdown.js +++ b/dist/modules/dropdown.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/dropdown.min.js b/dist/modules/dropdown.min.js index b08434662..b62ee995f 100644 --- a/dist/modules/dropdown.min.js +++ b/dist/modules/dropdown.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/dropdown.tpl.js b/dist/modules/dropdown.tpl.js index a71cc6d12..d3e09d535 100644 --- a/dist/modules/dropdown.tpl.js +++ b/dist/modules/dropdown.tpl.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/dropdown.tpl.min.js b/dist/modules/dropdown.tpl.min.js index 85710d5c1..7e0fc87ff 100644 --- a/dist/modules/dropdown.tpl.min.js +++ b/dist/modules/dropdown.tpl.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/modal.js b/dist/modules/modal.js index 375ab803c..f9522d24e 100644 --- a/dist/modules/modal.js +++ b/dist/modules/modal.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/modal.min.js b/dist/modules/modal.min.js index 9ae62c4c8..612df2296 100644 --- a/dist/modules/modal.min.js +++ b/dist/modules/modal.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/modal.tpl.js b/dist/modules/modal.tpl.js index 0e6921f6b..ddef920c4 100644 --- a/dist/modules/modal.tpl.js +++ b/dist/modules/modal.tpl.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/modal.tpl.min.js b/dist/modules/modal.tpl.min.js index b85a9b9ac..2461b415b 100644 --- a/dist/modules/modal.tpl.min.js +++ b/dist/modules/modal.tpl.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/navbar.js b/dist/modules/navbar.js index 60ef617f7..ad1ce10ae 100644 --- a/dist/modules/navbar.js +++ b/dist/modules/navbar.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/navbar.min.js b/dist/modules/navbar.min.js index bcac692eb..271343741 100644 --- a/dist/modules/navbar.min.js +++ b/dist/modules/navbar.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/parse-options.js b/dist/modules/parse-options.js index 9cb30a655..87736562e 100644 --- a/dist/modules/parse-options.js +++ b/dist/modules/parse-options.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/parse-options.min.js b/dist/modules/parse-options.min.js index 6f0c393ce..dcfa3d8d8 100644 --- a/dist/modules/parse-options.min.js +++ b/dist/modules/parse-options.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/popover.js b/dist/modules/popover.js index 53ab8f4fd..9aa1b124c 100644 --- a/dist/modules/popover.js +++ b/dist/modules/popover.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/popover.min.js b/dist/modules/popover.min.js index f352b695f..3203521f8 100644 --- a/dist/modules/popover.min.js +++ b/dist/modules/popover.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/popover.tpl.js b/dist/modules/popover.tpl.js index ba39253fa..52e688733 100644 --- a/dist/modules/popover.tpl.js +++ b/dist/modules/popover.tpl.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/popover.tpl.min.js b/dist/modules/popover.tpl.min.js index a89634ec4..d4c3063ba 100644 --- a/dist/modules/popover.tpl.min.js +++ b/dist/modules/popover.tpl.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/raf.js b/dist/modules/raf.js index 8096b21a1..9876343cd 100644 --- a/dist/modules/raf.js +++ b/dist/modules/raf.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/raf.min.js b/dist/modules/raf.min.js index 25e26ec21..a5f95d34f 100644 --- a/dist/modules/raf.min.js +++ b/dist/modules/raf.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/scrollspy.js b/dist/modules/scrollspy.js index f569b5e08..14eaf094a 100644 --- a/dist/modules/scrollspy.js +++ b/dist/modules/scrollspy.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/scrollspy.min.js b/dist/modules/scrollspy.min.js index 517274584..b3ba36075 100644 --- a/dist/modules/scrollspy.min.js +++ b/dist/modules/scrollspy.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/select.js b/dist/modules/select.js index 1a1a1a22f..4f9cd602c 100644 --- a/dist/modules/select.js +++ b/dist/modules/select.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/select.min.js b/dist/modules/select.min.js index 3c74e8783..1e9ffeab0 100644 --- a/dist/modules/select.min.js +++ b/dist/modules/select.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/select.tpl.js b/dist/modules/select.tpl.js index 194f88db7..f5a299987 100644 --- a/dist/modules/select.tpl.js +++ b/dist/modules/select.tpl.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/select.tpl.min.js b/dist/modules/select.tpl.min.js index e23e2c93c..e0c66b1b6 100644 --- a/dist/modules/select.tpl.min.js +++ b/dist/modules/select.tpl.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/tab.js b/dist/modules/tab.js index 8e749dc48..518d3af1f 100644 --- a/dist/modules/tab.js +++ b/dist/modules/tab.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT @@ -25,26 +25,43 @@ angular.module('mgcrea.ngStrap.tab', []).provider('$tab', function() { self.$panes = $scope.$panes = []; self.$activePaneChangeListeners = self.$viewChangeListeners = []; self.$push = function(pane) { + if (angular.isUndefined(self.$panes.$active)) { + $scope.$setActive(pane.name || 0); + } self.$panes.push(pane); }; self.$remove = function(pane) { var index = self.$panes.indexOf(pane); - var activeIndex = self.$panes.$active; + var active = self.$panes.$active; + var activeIndex; + if (angular.isString(active)) { + activeIndex = self.$panes.map(function(pane) { + return pane.name; + }).indexOf(active); + } else { + activeIndex = self.$panes.$active; + } self.$panes.splice(index, 1); if (index < activeIndex) { activeIndex--; } else if (index === activeIndex && activeIndex === self.$panes.length) { activeIndex--; } - self.$setActive(activeIndex); + if (activeIndex >= 0 && activeIndex < self.$panes.length) { + self.$setActive(self.$panes[activeIndex].name || activeIndex); + } else { + self.$setActive(); + } }; - self.$panes.$active = 0; self.$setActive = $scope.$setActive = function(value) { self.$panes.$active = value; self.$activePaneChangeListeners.forEach(function(fn) { fn(); }); }; + self.$isActive = $scope.$isActive = function($pane, $index) { + return self.$panes.$active === $pane.name || self.$panes.$active === $index; + }; }; this.$get = function() { var $tab = {}; @@ -70,7 +87,7 @@ angular.module('mgcrea.ngStrap.tab', []).provider('$tab', function() { ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active); }); ngModelCtrl.$formatters.push(function(modelValue) { - bsTabsCtrl.$setActive(modelValue * 1); + bsTabsCtrl.$setActive(modelValue); return modelValue; }); } @@ -80,7 +97,7 @@ angular.module('mgcrea.ngStrap.tab', []).provider('$tab', function() { parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active); }); scope.$watch(attrs.bsActivePane, function(newValue, oldValue) { - bsTabsCtrl.$setActive(newValue * 1); + bsTabsCtrl.$setActive(newValue); }, true); } } @@ -96,6 +113,7 @@ angular.module('mgcrea.ngStrap.tab', []).provider('$tab', function() { attrs.$observe('title', function(newValue, oldValue) { scope.title = $sce.trustAsHtml(newValue); }); + scope.name = attrs.name; if (bsTabsCtrl.$options.animation) { element.addClass(bsTabsCtrl.$options.animation); } @@ -108,8 +126,7 @@ angular.module('mgcrea.ngStrap.tab', []).provider('$tab', function() { }); function render() { var index = bsTabsCtrl.$panes.indexOf(scope); - var active = bsTabsCtrl.$panes.$active; - $animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass); + $animate[bsTabsCtrl.$isActive(scope, index) ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass); } bsTabsCtrl.$activePaneChangeListeners.push(function() { render(); diff --git a/dist/modules/tab.min.js b/dist/modules/tab.min.js index 4e5a21e38..e5f8e53af 100644 --- a/dist/modules/tab.min.js +++ b/dist/modules/tab.min.js @@ -1,9 +1,9 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT */ -'use strict';angular.module('mgcrea.ngStrap.tab',[]).provider('$tab',function(){var e=this.defaults={animation:'am-fade',template:'tab/tab.tpl.html',navClass:'nav-tabs',activeClass:'active'},a=this.controller=function(a,n,t){var s=this;s.$options=angular.copy(e),angular.forEach(['animation','navClass','activeClass'],function(e){angular.isDefined(t[e])&&(s.$options[e]=t[e])}),a.$navClass=s.$options.navClass,a.$activeClass=s.$options.activeClass,s.$panes=a.$panes=[],s.$activePaneChangeListeners=s.$viewChangeListeners=[],s.$push=function(e){s.$panes.push(e)},s.$remove=function(e){var a=s.$panes.indexOf(e),n=s.$panes.$active;s.$panes.splice(a,1),n>a?n--:a===n&&n===s.$panes.length&&n--,s.$setActive(n)},s.$panes.$active=0,s.$setActive=a.$setActive=function(e){s.$panes.$active=e,s.$activePaneChangeListeners.forEach(function(e){e()})}};this.$get=function(){var n={};return n.defaults=e,n.controller=a,n}}).directive('bsTabs',['$window','$animate','$tab','$parse',function(e,a,n,t){var s=n.defaults;return{require:['?ngModel','bsTabs'],transclude:!0,scope:!0,controller:['$scope','$element','$attrs',n.controller],templateUrl:function(e,a){return a.template||s.template},link:function(e,a,n,s){var i=s[0],o=s[1];if(i&&(o.$activePaneChangeListeners.push(function(){i.$setViewValue(o.$panes.$active)}),i.$formatters.push(function(e){return o.$setActive(1*e),e})),n.bsActivePane){var c=t(n.bsActivePane);o.$activePaneChangeListeners.push(function(){c.assign(e,o.$panes.$active)}),e.$watch(n.bsActivePane,function(e,a){o.$setActive(1*e)},!0)}}}}]).directive('bsPane',['$window','$animate','$sce',function(e,a,n){return{require:['^?ngModel','^bsTabs'],scope:!0,link:function(e,t,s,i){function o(){var n=c.$panes.indexOf(e),s=c.$panes.$active;a[n===s?'addClass':'removeClass'](t,c.$options.activeClass)}var c=(i[0],i[1]);t.addClass('tab-pane'),s.$observe('title',function(a,t){e.title=n.trustAsHtml(a)}),c.$options.animation&&t.addClass(c.$options.animation),s.$observe('disabled',function(a,n){e.disabled=e.$eval(a)}),c.$push(e),e.$on('$destroy',function(){c.$remove(e)}),c.$activePaneChangeListeners.push(function(){o()}),o()}}}]); +'use strict';angular.module('mgcrea.ngStrap.tab',[]).provider('$tab',function(){var e=this.defaults={animation:'am-fade',template:'tab/tab.tpl.html',navClass:'nav-tabs',activeClass:'active'},n=this.controller=function(n,a,t){var s=this;s.$options=angular.copy(e),angular.forEach(['animation','navClass','activeClass'],function(e){angular.isDefined(t[e])&&(s.$options[e]=t[e])}),n.$navClass=s.$options.navClass,n.$activeClass=s.$options.activeClass,s.$panes=n.$panes=[],s.$activePaneChangeListeners=s.$viewChangeListeners=[],s.$push=function(e){angular.isUndefined(s.$panes.$active)&&n.$setActive(e.name||0),s.$panes.push(e)},s.$remove=function(e){var n,a=s.$panes.indexOf(e),t=s.$panes.$active;n=angular.isString(t)?s.$panes.map(function(e){return e.name}).indexOf(t):s.$panes.$active,s.$panes.splice(a,1),n>a?n--:a===n&&n===s.$panes.length&&n--,n>=0&&n $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n bsTabsCtrl.$setActive(modelValue * 1);\n return modelValue;\n });\n\n }\n\n if (attrs.bsActivePane) {\n // adapted from angularjs ngModelController bindings\n // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n // Update bsActivePane value with change\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n });\n\n // watch bsActivePane for value changes\n scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n bsTabsCtrl.$setActive(newValue * 1);\n }, true);\n }\n }\n };\n\n })\n\n .directive('bsPane', function($window, $animate, $sce) {\n\n return {\n require: ['^?ngModel', '^bsTabs'],\n scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // Add base class\n element.addClass('tab-pane');\n\n // Observe title attribute for change\n attrs.$observe('title', function(newValue, oldValue) {\n scope.title = $sce.trustAsHtml(newValue);\n });\n\n // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\n }\n\n attrs.$observe('disabled', function(newValue, oldValue) {\n scope.disabled = scope.$eval(newValue);\n });\n\n // Push pane to parent bsTabs controller\n bsTabsCtrl.$push(scope);\n\n // remove pane from tab controller when pane is destroyed\n scope.$on('$destroy', function() {\n bsTabsCtrl.$remove(scope);\n });\n\n function render() {\n var index = bsTabsCtrl.$panes.indexOf(scope);\n var active = bsTabsCtrl.$panes.$active;\n $animate[index === active ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["modules/tab.js"],"names":["angular","controller","provider","$scope","$element","defaults","this","self","$options","forEach","navClass","activeClass","$activeClass","$panes","$activePaneChangeListeners","$push","pane","isUndefined","$active","key","$attrs","$navClass","$remove","index","active","activeIndex","indexOf","splice","map","$setActive","length","value","name","fn","$pane","$get","$tab","scope","require","transclude","directive","templateUrl","attr","template","link","postLink","ngModelCtrl","bsTabsCtrl","$setViewValue","$formatters","push","attrs","modelValue","bsActivePane","parsedBsActivePane","assign","$parse","$watch","newValue","oldValue","addClass","$window","$animate","$sce","title","trustAsHtml","render","$isActive","element","animation","$observe","disabled"],"mappings":"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","file":"modules/tab.min.js","sourcesContent":["'use strict';\n\nangular.module('mgcrea.ngStrap.tab', [])\n\n .provider('$tab', function() {\n\n var defaults = this.defaults = {\n animation: 'am-fade',\n template: 'tab/tab.tpl.html',\n navClass: 'nav-tabs',\n activeClass: 'active'\n };\n\n var controller = this.controller = function($scope, $element, $attrs) {\n var self = this;\n\n // Attributes options\n self.$options = angular.copy(defaults);\n angular.forEach(['animation', 'navClass', 'activeClass'], function(key) {\n if(angular.isDefined($attrs[key])) self.$options[key] = $attrs[key];\n });\n\n // Publish options on scope\n $scope.$navClass = self.$options.navClass;\n $scope.$activeClass = self.$options.activeClass;\n\n self.$panes = $scope.$panes = [];\n\n // Please use $activePaneChangeListeners if you use `bsActivePane`\n // Because we removed `ngModel` as default, we rename viewChangeListeners to\n // activePaneChangeListeners to make more sense.\n self.$activePaneChangeListeners = self.$viewChangeListeners = [];\n\n self.$push = function(pane) {\n if(angular.isUndefined(self.$panes.$active)) {\n $scope.$setActive(pane.name || 0);\n }\n self.$panes.push(pane);\n };\n\n self.$remove = function(pane) {\n var index = self.$panes.indexOf(pane);\n var active = self.$panes.$active;\n var activeIndex;\n if(angular.isString(active)) {\n activeIndex = self.$panes.map(function(pane) {\n return pane.name;\n }).indexOf(active);\n } else {\n activeIndex = self.$panes.$active;\n }\n\n // remove pane from $panes array\n self.$panes.splice(index, 1);\n\n if (index < activeIndex) {\n // we removed a pane before the active pane, so we need to\n // decrement the active pane index\n activeIndex--;\n }\n else if (index === activeIndex && activeIndex === self.$panes.length) {\n // we remove the active pane and it was the one at the end,\n // so select the previous one\n activeIndex--;\n }\n if(activeIndex >= 0 && activeIndex < self.$panes.length) {\n self.$setActive(self.$panes[activeIndex].name || activeIndex);\n } else {\n self.$setActive();\n }\n };\n\n self.$setActive = $scope.$setActive = function(value) {\n self.$panes.$active = value;\n self.$activePaneChangeListeners.forEach(function(fn) {\n fn();\n });\n };\n\n self.$isActive = $scope.$isActive = function($pane, $index) {\n return self.$panes.$active === $pane.name || self.$panes.$active === $index;\n };\n\n };\n\n this.$get = function() {\n var $tab = {};\n $tab.defaults = defaults;\n $tab.controller = controller;\n return $tab;\n };\n\n })\n\n .directive('bsTabs', function($window, $animate, $tab, $parse) {\n\n var defaults = $tab.defaults;\n\n return {\n require: ['?ngModel', 'bsTabs'],\n transclude: true,\n scope: true,\n controller: ['$scope', '$element', '$attrs', $tab.controller],\n templateUrl: function(element, attr) {\n return attr.template || defaults.template;\n },\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // 'ngModel' does interfere with form validation\n // and status, use `bsActivePane` instead to avoid it\n if(ngModelCtrl) {\n\n // Update the modelValue following\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n ngModelCtrl.$setViewValue(bsTabsCtrl.$panes.$active);\n });\n\n // modelValue -> $formatters -> viewValue\n ngModelCtrl.$formatters.push(function(modelValue) {\n // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n bsTabsCtrl.$setActive(modelValue);\n return modelValue;\n });\n\n }\n\n if (attrs.bsActivePane) {\n // adapted from angularjs ngModelController bindings\n // https://github.com/angular/angular.js/blob/v1.3.1/src%2Fng%2Fdirective%2Finput.js#L1730\n var parsedBsActivePane = $parse(attrs.bsActivePane);\n\n // Update bsActivePane value with change\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n parsedBsActivePane.assign(scope, bsTabsCtrl.$panes.$active);\n });\n\n // watch bsActivePane for value changes\n scope.$watch(attrs.bsActivePane, function(newValue, oldValue) {\n bsTabsCtrl.$setActive(newValue);\n }, true);\n }\n }\n };\n\n })\n\n .directive('bsPane', function($window, $animate, $sce) {\n\n return {\n require: ['^?ngModel', '^bsTabs'],\n scope: true,\n link: function postLink(scope, element, attrs, controllers) {\n\n var ngModelCtrl = controllers[0];\n var bsTabsCtrl = controllers[1];\n\n // Add base class\n element.addClass('tab-pane');\n\n // Observe title attribute for change\n attrs.$observe('title', function(newValue, oldValue) {\n scope.title = $sce.trustAsHtml(newValue);\n });\n\n // Save tab name into scope\n scope.name = attrs.name;\n\n // Add animation class\n if(bsTabsCtrl.$options.animation) {\n element.addClass(bsTabsCtrl.$options.animation);\n }\n\n attrs.$observe('disabled', function(newValue, oldValue) {\n scope.disabled = scope.$eval(newValue);\n });\n\n // Push pane to parent bsTabs controller\n bsTabsCtrl.$push(scope);\n\n // remove pane from tab controller when pane is destroyed\n scope.$on('$destroy', function() {\n bsTabsCtrl.$remove(scope);\n });\n\n function render() {\n var index = bsTabsCtrl.$panes.indexOf(scope);\n $animate[bsTabsCtrl.$isActive(scope, index) ? 'addClass' : 'removeClass'](element, bsTabsCtrl.$options.activeClass);\n }\n\n bsTabsCtrl.$activePaneChangeListeners.push(function() {\n render();\n });\n render();\n\n }\n };\n\n });\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/dist/modules/tab.tpl.js b/dist/modules/tab.tpl.js index 5a1fdb016..39c40b98b 100644 --- a/dist/modules/tab.tpl.js +++ b/dist/modules/tab.tpl.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT @@ -8,5 +8,5 @@ 'use strict'; angular.module('mgcrea.ngStrap.tab').run([ '$templateCache', function($templateCache) { - $templateCache.put('tab/tab.tpl.html', '
'); + $templateCache.put('tab/tab.tpl.html', '
'); } ]); \ No newline at end of file diff --git a/dist/modules/tab.tpl.min.js b/dist/modules/tab.tpl.min.js index 6907a4080..19b7ccfb9 100644 --- a/dist/modules/tab.tpl.min.js +++ b/dist/modules/tab.tpl.min.js @@ -1,8 +1,8 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT */ -'use strict';angular.module('mgcrea.ngStrap.tab').run(['$templateCache',function(a){a.put('tab/tab.tpl.html','
')}]); \ No newline at end of file +'use strict';angular.module('mgcrea.ngStrap.tab').run(['$templateCache',function(a){a.put('tab/tab.tpl.html','
')}]); \ No newline at end of file diff --git a/dist/modules/timepicker.js b/dist/modules/timepicker.js index 34dbf37f2..764b04781 100644 --- a/dist/modules/timepicker.js +++ b/dist/modules/timepicker.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/timepicker.min.js b/dist/modules/timepicker.min.js index b6bc95148..5d148a8a6 100644 --- a/dist/modules/timepicker.min.js +++ b/dist/modules/timepicker.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/timepicker.tpl.js b/dist/modules/timepicker.tpl.js index e41ac1d32..9e39ca2dc 100644 --- a/dist/modules/timepicker.tpl.js +++ b/dist/modules/timepicker.tpl.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/timepicker.tpl.min.js b/dist/modules/timepicker.tpl.min.js index 49d8bc817..42d120c9c 100644 --- a/dist/modules/timepicker.tpl.min.js +++ b/dist/modules/timepicker.tpl.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/tooltip.js b/dist/modules/tooltip.js index a15fb1e95..6206c6335 100644 --- a/dist/modules/tooltip.js +++ b/dist/modules/tooltip.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/tooltip.min.js b/dist/modules/tooltip.min.js index ee86b20d2..fc652aa10 100644 --- a/dist/modules/tooltip.min.js +++ b/dist/modules/tooltip.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/tooltip.tpl.js b/dist/modules/tooltip.tpl.js index 512386de4..5b25107a9 100644 --- a/dist/modules/tooltip.tpl.js +++ b/dist/modules/tooltip.tpl.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/tooltip.tpl.min.js b/dist/modules/tooltip.tpl.min.js index c939e92dc..ff35d37e5 100644 --- a/dist/modules/tooltip.tpl.min.js +++ b/dist/modules/tooltip.tpl.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/typeahead.js b/dist/modules/typeahead.js index 613f1c521..c9385a459 100644 --- a/dist/modules/typeahead.js +++ b/dist/modules/typeahead.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/typeahead.min.js b/dist/modules/typeahead.min.js index 45e4c4de6..3573fb435 100644 --- a/dist/modules/typeahead.min.js +++ b/dist/modules/typeahead.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/typeahead.tpl.js b/dist/modules/typeahead.tpl.js index 171fdaa4b..7630d6dac 100644 --- a/dist/modules/typeahead.tpl.js +++ b/dist/modules/typeahead.tpl.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/dist/modules/typeahead.tpl.min.js b/dist/modules/typeahead.tpl.min.js index 29c7c660c..dc7b52f19 100644 --- a/dist/modules/typeahead.tpl.min.js +++ b/dist/modules/typeahead.tpl.min.js @@ -1,6 +1,6 @@ /** * angular-strap - * @version v2.2.2 - 2015-05-15 + * @version v2.2.3 - 2015-05-20 * @link http://mgcrea.github.io/angular-strap * @author Olivier Louvignes (https://github.com/mgcrea) * @license MIT License, http://www.opensource.org/licenses/MIT diff --git a/docs/bower.json b/docs/bower.json index 997a09578..5771b36c6 100644 --- a/docs/bower.json +++ b/docs/bower.json @@ -4,10 +4,10 @@ "angular": "~1.3.15", "angular-animate": "~1.3.15", "angular-i18n": "~1.3.15", - "angular-motion": "~0.4.1", + "angular-motion": "~0.4.2", "angular-route": "~1.3.15", "bootstrap": "~3.3.4", - "bootstrap-additions": "~0.3.0", + "bootstrap-additions": "~0.3.1", "fastclick": "~1.0.6", "font-awesome": "~4.3.0", "highlightjs": "~8.5.0" diff --git a/docs/scripts/app.js b/docs/scripts/app.js index dabe7a2cb..283cf28d5 100644 --- a/docs/scripts/app.js +++ b/docs/scripts/app.js @@ -2,7 +2,7 @@ angular.module('mgcrea.ngStrapDocs', ['mgcrea.ngStrap', 'mgcrea.ngPlunkr', 'ngRoute', 'ngAnimate']) -.constant('version', 'v2.2.2') +.constant('version', 'v2.2.3') .config(function($plunkrProvider, version) { diff --git a/docs/views/partials/header.html b/docs/views/partials/header.html index d80184c45..28bcd19c7 100644 --- a/docs/views/partials/header.html +++ b/docs/views/partials/header.html @@ -7,7 +7,7 @@

AngularStrap

  • - +
  • diff --git a/package.json b/package.json index aafd8a7f1..9ad8f5dfc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "angular-strap", "description": "AngularStrap - AngularJS directives for Bootstrap", - "version": "2.2.2", + "version": "2.2.3", "keywords": [ "angular", "bootstrap"