{"version":3,"sources":["angular-strap.js","typeahead/typeahead.js","helpers/compiler.js","dropdown/dropdown.js","tooltip/tooltip.js","timepicker/timepicker.js","tab/tab.js","select/select.js","scrollspy/scrollspy.js","popover/popover.js","navbar/navbar.js","modal/modal.js","helpers/raf.js","helpers/parse-options.js","helpers/dimensions.js","helpers/debounce.js","helpers/date-parser.js","helpers/date-formatter.js","button/button.js","datepicker/datepicker.js","collapse/collapse.js","aside/aside.js","alert/alert.js","affix/affix.js","module.js"],"names":["prefixEvent","undefined","templateUrl","options","cache","$templateCache","then","element","res","fetchTemplate","template","fetchPromises","module","$http","get","defaults","animation","prefixClass","data","this","compile","controller","console","controllerAs","resolve","locals","bindToController","angular","forEach","value","isString","$injector","key","transformTemplate","identity","extend","$template","when","$q","all","templateEl","Error","findElement","contentTemplate","templates","contentEl","removeAttr","html","replace","next","remove","outerHTML","link","scope","trim","contents","linkFn","invokeCtrl","children","instance","ctrl","isObject","arguments","apply","bsCompilerService","$inject","trigger","provider","container","keyboard","delay","minLength","filter","limit","autoSelect","comparator","trimValue","$get","$typeahead","parentScope","$resetMatches","$window","$rootScope","$tooltip","$$rAF","$timeout","$matches","config","$$postDigest","$scope","activate","$activeIndex","select","index","$select","evt","matches","$isVisible","safeDigest","update","$render","$emit","onSelect","$setViewValue","length","isDefined","isFunction","equals","$onMouseDown","preventDefault","stopPropagation","clientTop","active","offsetTop","clientBottom","highWatermark","scrollTop","Math","lowWatermark","clientHeight","keyCode","$$updateScrollTop","$digest","show","isUndefined","$element","hide","$onKeyDown","$$phase","TypeaheadFactory","array","$filter","expression","directive","results","postLink","attr","restrict","require","falseValueRegExp","bsKey","charAt","toUpperCase","slice","test","bsOptions","parsedOptions","$parseOptions","typeahead","watchedOptions","$watchCollection","values","watchOptions","$match","$watch","ngModel","newValue","oldValue","$modelValue","valuesFn","selectMode","$viewValue","substring","displayValue","$formatters","push","modelValue","selected","ss","selectionStart","val","selectionEnd","setSelectionRange","sd","label","destroy","$on","target","placement","titleTemplate","title","type","autoClose","bsEnabled","mouseDownPreventDefault","mouseDownStopPropagation","viewport","selector","padding","TooltipFactory","promise","$bsCompiler","split","clearTimeout","hoverState","onShow","leaveAnimateCallback","destroyTipElement","onHide","_tipToHide","triggers","nodeName","on","isTouch","toggle","enter","unbindTriggerEvents","$onFocusElementMouseDown","off","i","bindKeyboardEvents","tipElement","$onKeyUp","unbindKeyboardEvents","_autoCloseEventsBinded","bindAutoCloseEvents","$body","unbindAutoCloseEvents","stopEventPropagation","event","getPosition","elRect","getBoundingClientRect","rect","p","width","height","top","left","dimensions","offset","el","scroll","outerDims","isBody","document","documentElement","body","prop","clientWidth","innerHeight","position","actualWidth","actualHeight","marginLeft","isNaN","setOffset","using","parseInt","props","css","right","marginTop","tip","offsetHeight","getViewportAdjustedDelta","delta","offsetWidth","isVertical","arrowDelta","replaceArrow","arrowOffsetPosition","viewportDimensions","$viewport","topEdgeOffset","bottomEdgeOffset","viewportPadding","leftEdgeOffset","rightEdgeOffset","dimension","isHorizontal","$arrow","timeout","$isShown","tipScope","$destroy","$options","$promise","$new","toLowerCase","$id","map","parseFloat","$sce","trustAsHtml","$setEnabled","id","$hide","setEnabled","isEnabled","compileData","tipContainer","init","bindTriggerEvents","isElement","focus","onBeforeShow","after","parent","lastChild","display","visibility","clonedElement","addClass","version","prepend","$applyPlacement","$animate","enterAnimateCallback","_blur","onBeforeHide","blur","leave","autoPlace","autoToken","elementPosition","tipWidth","tipHeight","viewportPosition","originalPlacement","removeClass","tipPosition","getCalculatedOffset","applyPlacement","$root","query","querySelectorAll","isNative","tooltip","transclusion","$eval","dataTarget","hasOwnProperty","$observe","bsTooltip","bsShow","match","setViewport","useNative","timeType","timeFormat","timezone","modelTimeFormat","autoclose","minTime","maxTime","Infinity","hourStep","minuteStep","secondStep","roundDisplay","iconUp","iconDown","arrowBehavior","$timepicker","timepickerFactory","formatDate","format","viewDate","hour","startDate","getHours","meridian","coeff","selRange","end","start","collapse","moveStart","moveEnd","focusElement","_init","floorMinutes","time","floor","lang","selectedIndex","date","defaultDate","second","getSeconds","millisecond","getMilliseconds","$dateValue","hoursFormat","$dateFormatter","timeSeparator","minute","minutesFormat","secondsFormat","showSeconds","$iconUp","$moveIndex","$switchMeridian","switchMeridian","isDate","getMinutes","getTime","$build","$isBuilt","keep","Date","setHours","setMinutes","setSeconds","copy","midIndex","hours","disabled","minutes","$date","seconds","rows","$isDisabled","showAM","$isSelected","isAM","selectedTime","$arrowAction","$setTimeByStep","newDate","targetDate","targetEl","triggerHandler","hoursLength","minutesLength","sepLength","lateralMove","count","selectRange","incr","isSeconds","isMeridian","secondsLength","createSelection","createTextRange","_destroy","_show","_hide","navigator","userAgent","isMaxValid","isValid","parsedTime","isMinValid","setFullYear","$setValidity","$parsers","unshift","viewValue","getTimeFormattedString","timepicker","dateParser","$dateParser","validateAgainstMinMaxTime","timezoneOffsetAdjust","NaN","parse","self","navClass","activeClass","$activeClass","$panes","$activePaneChangeListeners","$push","pane","$active","$attrs","$navClass","$remove","activeIndex","indexOf","splice","$setActive","name","fn","$pane","$tab","transclude","ngModelCtrl","bsTabsCtrl","attrs","bsActivePane","parsedBsActivePane","assign","$parse","controllers","render","$isActive","multiple","allNoneButtons","sort","caretHtml","placeholder","allText","noneText","maxLength","maxLengthHtml","iconCheckmark","SelectFactory","$isMultiple","$showAllNoneButtons","$iconCheckmark","$allText","$activate","$selectNone","$updateActiveIndex","a","b","$apply","isArray","$getIndex","anchor","anchorCandidate","$selectScrollFix","$isIE","stopImmediatePropagation","ua","activeElement","tagName","e","dataMultiple","inputEl","addEventListener","join","$isEmpty","spies","$document","windowEl","debounce","bodyEl","throttle","ScrollSpyFactory","scrollEl","isWindowSpy","scrollId","$$count","$scrollspy","unbindViewContentLoaded","unbindIncludeContentLoaded","trackedElements","sortedElements","activeTarget","debouncedCheckOffsets","viewportHeight","debouncedCheckPosition","throttledCheckPosition","checkPositionWithEventLoop","checkOffsets","checkPosition","docEl","$activateElement","setTimeout","source","$getTrackedElement","targetElement","querySelector","trackedElement","trackElement","toDelete","untrackElement","scrollspy","childEl","child","content","$popover","PopoverFactory","requestAnimationFrame","bsPopover","popover","routeAttr","$navbar","liElements","li","liElement","pattern","path","RegExp","regexp","backdrop","size","zIndex","bodyElement","backdropCount","dialogBaseZindex","validSizes","ModalFactory","$modal","unbindBackdropEvents","modalElement","hideOnBackdropClick","backdropElement","preventEventDefault","modalScope","backdropBaseZindex","$show","bottom","destroyModalElement","z-index","defaultPrevented","customClass","minor","backdropAnimation","bindBackdropEvents","which","lg","sm","modalClass","bsModal","modal","dot","cancelAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","rafSupported","raf","timer","cancel","supported","$values","valueName","keyName","displayFn","valueFn","ParseOptionsFactory","groupByFn","factory","offsetParent","docElement","ownerDocument","outer","window","getComputedStyle","extra","currentStyle","boxRect","style","curPosition","curLeft","curCSSTop","curTop","calculatePosition","curElem","curCSSLeft","curOffset","call","offsetParentRect","offsetParentEl","offsetParentElement","func","immediate","args","context","callNow","leading","wait","trailing","year","$localeProvider","milliseconds","ParseDate","prototype","noop","indexOfCaseInsensitive","len","str","toString","strict","day","month","getFullYear","getMonth","proto","isNumeric","toDate","regExpMap","sss","$locale","dateFilter","mm","literalRegex","formatParts","escapedLiteralFormat","dateElements","keys","escapedFormat","isFormatStringLiteral","part","trimLiteralEscapeChars","dateRegexParts","escapeReservedSymbols","text","re","abstractRegex","buildDateParseRegex","setMapForFormat","buildDateAbstractRegex","buildDateParseValuesMap","Object","valuesMatch","keyIndex","valueKey","valuesFunctionMap","valueFunction","valuesRegex","exec","setFnMap","DateParserFactory","setMap","m","HH","H","hh","h","EEEE","EEE","DATETIME_FORMATS","SHORTDAY","dd","d","MMMM","MMM","SHORTMONTH","MM","M","DAY","yyyy","yy","y","MONTH","s","setDate","setMonth","regex","$format","regExpForFormat","baseDate","formatRegex","formatSetMap","fromDate","getDate","getDateForAttribute","today","substr","getTimeForAttribute","daylightSavingAdjust","undo","getTimezoneOffset","getDefaultLocale","getDatetimeFormat","weekdaysShort","splitTimeFormat","service","matchesSelector","DropdownFactory","$dropdown","onBodyClick","items","parentEl","hasClass","tAttrs","nextSibling","nodeType","parentNode","removeChild","dropdown","$button","constantValueRegExp","isInput","trueValue","falseValue","hasExoticValues","isActive","checked","toggleClass","bind","toggleEvent","v","dateType","dateFormat","modelDateFormat","dayFormat","monthFormat","yearFormat","monthTitleFormat","yearTitleFormat","strictFormat","minDate","maxDate","startView","minView","startWeek","daysOfWeekDisabled","hasToday","hasClear","iconLeft","iconRight","DatepickerFactory","$datepicker","pickerViews","views","$iconLeft","$iconRight","$hasToday","$picker","$selectPane","$views","$mode","$toggleMode","$setToday","$clear","setMode","updateDisabledDates","disabledDateRanges","dateRanges","$setDisabledEl","mode","pristine","$updateSelected","built","isDisabled","steps","getUTCFullYear","getUTCMonth","UTC","getUTCDate","shiftKey","altKey","onKeyDown","datepickerViews","previousValue","normalizeDateRanges","ranges","disabledRanges","datepicker","parsedDate","getDateFormattedString","validateAgainstMinMaxDate","disabledDates","arrays","mod","n","arr","weekDaysMin","weekDaysLabelsHtml","picker","weekDaysLabels","concat","firstDayOfMonth","firstDayOfMonthOffset","firstDate","firstDateOffset","build","days","isToday","toDateString","muted","showLabels","labels","isTodayDisabled","isSelected","getDay","months","lastDate","actualMonth","firstYear","years","actualYear","Array","setYear","startCollapsed","allowMultiple","activeIndexes","$targets","activeItems","activateItem","$collapse","$viewChangeListeners","$registerToggle","$toggles","$unregisterToggle","$unregisterTarget","deactivateItem","fixActiveItemIndexes","disallowToggle","$activeIndexes","bsCollapseCtrl","bsCollapseToggle","$registerTarget","action","AsideFactory","$aside","bsAside","aside","duration","dismissable","AlertFactory","$alert","bsAlert","alert","AffixFactory","inlineStyles","$affix","setWidth","reset","initialOffsetTop","getRequiredAffixClass","_unpin","getScrollTop","scrollHeight","getScrollHeight","pageYOffset","offsetBottom","elementHeight","initialAffixTop","affixed","unpin","$parseOffsets","affix","offsetUnpin","$onResize","initialTop","$debouncedOnResize","initialPosition","affixTarget","option"],"mappings":"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","file":"angular-strap.min.js","sourcesContent":["(function(window, document, undefined) {\n'use strict';\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      templateUrl: 'typeahead/typeahead.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      minLength: 1,\n      filter: 'bsAsyncFilter',\n      limit: 6,\n      autoSelect: false,\n      comparator: '',\n      trimValue: true\n    };\n\n    this.$get = function ($window, $rootScope, $tooltip, $$rAF, $timeout) {\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          // wrap in a $timeout so the results are updated\n          // before repositioning\n          safeDigest(scope);\n          $$rAF($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          if (angular.isDefined(options.onSelect) && angular.isFunction(options.onSelect)) {\n            options.onSelect(value, index, $typeahead);\n          }\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 index;\n          for (index = scope.$matches.length; index--;) {\n            if (angular.equals(scope.$matches[index].value, value)) break;\n          }\n          return index;\n        };\n\n        $typeahead.$onMouseDown = function (evt) {\n          // Prevent blur on mousedown\n          evt.preventDefault();\n          evt.stopPropagation();\n        };\n\n        $typeahead.$$updateScrollTop = function (container, index) {\n          if (index > -1 && index < container.children.length) {\n            var active = container.children[index];\n            var clientTop = active.offsetTop;\n            var clientBottom = active.offsetTop + active.clientHeight;\n            var highWatermark = container.scrollTop;\n            var lowWatermark = container.scrollTop + container.clientHeight;\n\n            // active entry overlaps top border\n            if (clientBottom >= highWatermark && clientTop < highWatermark) {\n              container.scrollTop = Math.max(0, container.scrollTop - container.clientHeight);\n            } else if (clientBottom > lowWatermark) {\n              // top of active element is invisible because it's below the bottom of the visible container window\n              container.scrollTop = clientTop;\n            }\n          }\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          // Navigate with keyboard\n          } else if (evt.keyCode === 38 && scope.$activeIndex > 0) {\n            scope.$activeIndex--;\n          } else if (evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) {\n            scope.$activeIndex++;\n          } else if (angular.isUndefined(scope.$activeIndex)) {\n            scope.$activeIndex = 0;\n          }\n\n          // update scrollTop property on $typeahead when scope.$activeIndex is not in visible area\n          $typeahead.$$updateScrollTop($typeahead.$element[0], scope.$activeIndex);\n          scope.$digest();\n        };\n\n        // Overrides\n\n        var show = $typeahead.show;\n        $typeahead.show = function () {\n          show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed immediately.\n          $timeout(function () {\n            if ($typeahead.$element) {\n              $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n              if (options.keyboard) {\n                if (element) element.on('keydown', $typeahead.$onKeyDown);\n              }\n            }\n          }, 0, false);\n        };\n\n        var hide = $typeahead.hide;\n        $typeahead.hide = function () {\n          if ($typeahead.$element) $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n          if (options.keyboard) {\n            if (element) element.off('keydown', $typeahead.$onKeyDown);\n          }\n          if (!options.autoSelect) {\n            $typeahead.activate(-1);\n          }\n          hide();\n        };\n\n        return $typeahead;\n\n      }\n\n      // Helper functions\n\n      function safeDigest (scope) {\n        /* eslint-disable no-unused-expressions */\n        scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n        /* eslint-enable no-unused-expressions */\n      }\n\n      TypeaheadFactory.defaults = defaults;\n      return TypeaheadFactory;\n\n    };\n\n  })\n\n  .filter('bsAsyncFilter', function ($filter) {\n    return function (array, expression, comparator) {\n      if (array && angular.isFunction(array.then)) {\n        return array.then(function (results) {\n          return $filter('filter')(results, expression, comparator);\n        });\n      }\n      return $filter('filter')(array, expression, comparator);\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        // Fixes firefox bug when using objects in model with typeahead\n        // Yes this breaks any other directive using a 'change' event on this input,\n        // but if it is using the 'change' event why is it used with typeahead?\n        element.off('change');\n\n        // Directive options\n        var options = {\n          scope: scope\n        };\n        angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', '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', 'filter'], function (key) {\n          if (angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n        });\n\n        // bind functions from the attrs to the show, hide and select events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide', 'onSelect'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\n        });\n\n        // Disable browser autocompletion\n        if (!element.attr('autocomplete')) element.attr('autocomplete', 'off');\n\n        // Build proper bsOptions\n        var filter = angular.isDefined(options.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) {\n          bsOptions += ' | ' + filter + ':$viewValue';\n          if (comparator) bsOptions += ':' + comparator;\n        }\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              typeahead.update(values);\n              // Queue a new rendering that will leverage collection loading\n              controller.$render();\n            });\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function (modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var displayValue = parsedOptions.displayValue(modelValue);\n\n          // If we can determine the displayValue, use that\n          if (displayValue) {\n            return displayValue;\n          }\n\n          // If there's no display value, attempt to use the modelValue.\n          // If the model is an object not much we can do\n          if (angular.isDefined(modelValue) && typeof modelValue !== 'object') {\n            return modelValue;\n          }\n          return '';\n        });\n\n        // Model rendering in view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          if (controller.$isEmpty(controller.$viewValue)) {\n            return element.val('');\n          }\n          var index = typeahead.$getIndex(controller.$modelValue);\n          var selected = index !== -1 ? 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          var ss = element[0].selectionStart;\n          var sd = element[0].selectionEnd;\n          element.val(options.trimValue === false ? value : value.trim());\n          element[0].setSelectionRange(ss, sd);\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// Source: tooltip/tooltip.js\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.core', '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      templateUrl: 'tooltip/tooltip.tpl.html',\n      template: '',\n      titleTemplate: 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      mouseDownPreventDefault: true,\n      mouseDownStopPropagation: true,\n      viewport: {\n        selector: 'body',\n        padding: 0\n      }\n    };\n\n    this.$get = function ($window, $rootScope, $bsCompiler, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n      var isNative = /(ip[ao]d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n      var $body = angular.element($window.document);\n\n      function TooltipFactory (element, config) {\n\n        var $tooltip = {};\n\n        // Common vars\n        var options = $tooltip.$options = angular.extend({}, defaults, config);\n        var promise = $tooltip.$promise = $bsCompiler.compile(options);\n        var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n        var nodeName = element[0].nodeName.toLowerCase();\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;\n        var hoverState;\n\n        // Fetch, compile then initialize tooltip\n        var compileData;\n        var tipElement;\n        var tipContainer;\n        var tipScope;\n        promise.then(function (data) {\n          compileData = data;\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              if (options.trigger === 'focus') {\n                element[0].focus();\n              } else {\n                $tooltip.show();\n              }\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          if (angular.isDefined(options.onBeforeShow) && angular.isFunction(options.onBeforeShow)) {\n            options.onBeforeShow($tooltip);\n          }\n          var parent;\n          var 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 = compileData.link(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          if (after) {\n            after.after(tipElement);\n          } else {\n            parent.prepend(tipElement);\n          }\n\n          $tooltip.$isShown = scope.$isShown = true;\n          safeDigest(scope);\n\n          // Now, apply placement\n          $tooltip.$applyPlacement();\n\n          // Once placed, animate it.\n          // Support v1.2+ $animate\n          // https://github.com/angular/angular.js/issues/11713\n          if (angular.version.minor <= 2) {\n            $animate.enter(tipElement, parent, after, enterAnimateCallback);\n          } else {\n            $animate.enter(tipElement, parent, after).then(enterAnimateCallback);\n          }\n          safeDigest(scope);\n\n          $$rAF(function () {\n            // Once the tooltip is placed and the animation starts, make the tooltip visible\n            if (tipElement) tipElement.css({visibility: 'visible'});\n\n            // Bind events\n            if (options.keyboard) {\n              if (options.trigger !== 'focus') {\n                $tooltip.focus();\n              }\n              bindKeyboardEvents();\n            }\n          });\n\n          if (options.autoClose) {\n            bindAutoCloseEvents();\n          }\n\n        };\n\n        function enterAnimateCallback () {\n          scope.$emit(options.prefixEvent + '.show', $tooltip);\n          if (angular.isDefined(options.onShow) && angular.isFunction(options.onShow)) {\n            options.onShow($tooltip);\n          }\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          if (angular.isDefined(options.onBeforeHide) && angular.isFunction(options.onBeforeHide)) {\n            options.onBeforeHide($tooltip);\n          }\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          if (tipElement !== null) {\n            // Support v1.2+ $animate\n            // https://github.com/angular/angular.js/issues/11713\n            if (angular.version.minor <= 2) {\n              $animate.leave(tipElement, leaveAnimateCallback);\n            } else {\n              $animate.leave(tipElement).then(leaveAnimateCallback);\n            }\n          }\n\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          if (angular.isDefined(options.onHide) && angular.isFunction(options.onHide)) {\n            options.onHide($tooltip);\n          }\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 (evt) {\n          if (evt) { evt.preventDefault(); }\n          if ($tooltip.$isShown) {\n            $tooltip.leave();\n          } else {\n            $tooltip.enter();\n          }\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          var autoToken = /\\s?auto?\\s?/i;\n          var 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          var tipWidth = tipElement.prop('offsetWidth');\n          var tipHeight = tipElement.prop('offsetHeight');\n\n          // Refresh viewport position\n          $tooltip.$viewport = options.viewport && findElement(options.viewport.selector || options.viewport);\n\n          // If we're auto placing, we need to check the positioning\n          if (autoPlace) {\n            var originalPlacement = placement;\n            var viewportPosition = getPosition($tooltip.$viewport);\n\n            if (/bottom/.test(originalPlacement) && elementPosition.bottom + tipHeight > viewportPosition.bottom) {\n              placement = originalPlacement.replace('bottom', 'top');\n            } else if (/top/.test(originalPlacement) && elementPosition.top - tipHeight < viewportPosition.top) {\n              placement = originalPlacement.replace('top', 'bottom');\n            }\n\n            if (/left/.test(originalPlacement) && elementPosition.left - tipWidth < viewportPosition.left) {\n              placement = placement.replace('left', 'right');\n            } else if (/right/.test(originalPlacement) && elementPosition.right + tipWidth > viewportPosition.width) {\n              placement = 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          if (options.mouseDownPreventDefault) { evt.preventDefault(); }\n          if (options.mouseDownStopPropagation) { evt.stopPropagation(); }\n          // Some browsers do not auto-focus buttons (eg. Safari)\n          if ($tooltip.$isShown) {\n            element[0].blur();\n          } else {\n            element[0].focus();\n          }\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' || trigger === 'contextmenu') {\n              element.on(trigger, $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              if (nodeName === 'button' && trigger !== 'hover') {\n                element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n              }\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' || trigger === 'contextmenu') {\n              element.off(trigger, $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              if (nodeName === 'button' && trigger !== 'hover') {\n                element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n              }\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          var 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          /* eslint-disable guard-for-in */\n          for (var p in elRect) { // eslint-disable-line\n            // DO NOT use hasOwnProperty when inspecting the return of getBoundingClientRect.\n            rect[p] = elRect[p];\n          }\n          /* eslint-enable guard-for-in */\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          var scroll = {scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.prop('scrollTop') || 0};\n          var 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                break;\n              default:\n                break;\n            }\n          } else if (split[0] === 'left' || split[0] === 'right') {\n            switch (split[1]) {\n              case 'top':\n                offset.top = position.top - actualHeight + position.height;\n                break;\n              case 'bottom':\n                offset.top = position.top;\n                break;\n              default:\n                break;\n            }\n          }\n\n          return offset;\n        }\n\n        function applyPlacement (offset, placement) {\n          var tip = tipElement[0];\n          var width = tip.offsetWidth;\n          var height = tip.offsetHeight;\n\n          // manually read margins because getBoundingClientRect includes difference\n          var marginTop = parseInt(dimensions.css(tip, 'margin-top'), 10);\n          var 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          var 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            var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight;\n            var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';\n\n            replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical);\n          }\n        }\n\n        // @source https://github.com/twbs/bootstrap/blob/v3.3.5/js/tooltip.js#L380\n        function getViewportAdjustedDelta (placement, position, actualWidth, actualHeight) {\n          var delta = {top: 0, left: 0};\n          if (!$tooltip.$viewport) return delta;\n\n          var viewportPadding = options.viewport && options.viewport.padding || 0;\n          var viewportDimensions = getPosition($tooltip.$viewport);\n\n          if (/right|left/.test(placement)) {\n            var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll;\n            var 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            var rightEdgeOffset = position.left + viewportPadding + actualWidth;\n            if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n              delta.left = viewportDimensions.left - leftEdgeOffset;\n            } else if (rightEdgeOffset > viewportDimensions.right) { // 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        /* eslint-disable no-unused-expressions */\n        scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n        /* eslint-enable no-unused-expressions */\n      }\n\n      function findElement (query, element) {\n        return angular.element((element || document).querySelectorAll(query));\n      }\n\n      return TooltipFactory;\n\n    };\n\n  })\n\n  .directive('bsTooltip', function ($window, $location, $sce, $parse, $tooltip, $$rAF) {\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink (scope, element, attr, transclusion) {\n\n        var tooltip;\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'titleTemplate', '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\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\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\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            if (angular.isDefined(oldValue)) {\n              $$rAF(function () {\n                if (tooltip) tooltip.$applyPlacement();\n              });\n            }\n          }\n        });\n\n        attr.$observe('disabled', function (newValue) {\n          if (newValue && tooltip.$isShown) {\n            tooltip.hide();\n          }\n        });\n\n        // Support scope as an object\n        if (attr.bsTooltip) {\n          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            if (angular.isDefined(oldValue)) {\n              $$rAF(function () {\n                if (tooltip) tooltip.$applyPlacement();\n              });\n            }\n          }, true);\n        }\n\n        // Visibility binding support\n        if (attr.bsShow) {\n          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            if (newValue === true) {\n              tooltip.show();\n            } else {\n              tooltip.hide();\n            }\n          });\n        }\n\n        // Enabled binding support\n        if (attr.bsEnabled) {\n          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            if (newValue === false) {\n              tooltip.setEnabled(false);\n            } else {\n              tooltip.setEnabled(true);\n            }\n          });\n        }\n\n        // Viewport support\n        if (attr.viewport) {\n          scope.$watch(attr.viewport, function (newValue) {\n            if (!tooltip || !angular.isDefined(newValue)) return;\n            tooltip.setViewport(newValue);\n          });\n        }\n\n        // Initialize popover\n        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: timepicker/timepicker.js\nangular.module('mgcrea.ngStrap.timepicker', ['mgcrea.ngStrap.helpers.dateParser', 'mgcrea.ngStrap.helpers.dateFormatter', 'mgcrea.ngStrap.tooltip'])\n\n  .provider('$timepicker', function () {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      defaultDate: 'auto',\n      // uncommenting the following line will break backwards compatability\n      // prefixEvent: 'timepicker',\n      prefixClass: 'timepicker',\n      placement: 'bottom-left',\n      templateUrl: '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 isNative = /(ip[ao]d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n      if (!defaults.lang) {\n        defaults.lang = $dateFormatter.getDefaultLocale();\n      }\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          // 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 = {\n          hour: startDate.getHours(),\n          meridian: startDate.getHours() < 12,\n          minute: startDate.getMinutes(),\n          second: startDate.getSeconds(),\n          millisecond: startDate.getMilliseconds()\n        };\n\n        var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n        var hoursFormat = $dateFormatter.hoursFormat(format);\n        var timeSeparator = $dateFormatter.timeSeparator(format);\n        var minutesFormat = $dateFormatter.minutesFormat(format);\n        var secondsFormat = $dateFormatter.secondsFormat(format);\n        var showSeconds = $dateFormatter.showSeconds(format);\n        var 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, {\n              hour: date.getHours(),\n              minute: date.getMinutes(),\n              second: date.getSeconds(),\n              millisecond: date.getMilliseconds()\n            });\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())) {\n            controller.$dateValue = options.defaultDate === 'today' ? new Date() : new Date(1970, 0, 1);\n          }\n\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 () {\n              $timepicker.hide(true);\n            });\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;\n          var midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n          var hours = [];\n          var 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({\n              date: hour,\n              label: formatDate(hour, hoursFormat),\n              selected: $timepicker.$date && $timepicker.$isSelected(hour, 0),\n              disabled: $timepicker.$isDisabled(hour, 0)\n            });\n          }\n          var minutes = [];\n          var 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({\n              date: minute,\n              label: formatDate(minute, minutesFormat),\n              selected: $timepicker.$date && $timepicker.$isSelected(minute, 1),\n              disabled: $timepicker.$isDisabled(minute, 1)\n            });\n          }\n          var seconds = [];\n          var 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({\n              date: second,\n              label: formatDate(second, secondsFormat),\n              selected: $timepicker.$date && $timepicker.$isSelected(second, 2),\n              disabled: $timepicker.$isDisabled(second, 2)\n            });\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 || startDate);\n          var hours = newDate.getHours();\n          var minutes = newDate.getMinutes();\n          var seconds = newDate.getSeconds();\n          if (index === 0) {\n            newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n          } else if (index === 1) {\n            newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\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, {\n              hour: targetDate.getHours()\n            });\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, {\n              minute: targetDate.getMinutes()\n            });\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, {\n              second: targetDate.getSeconds()\n            });\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) {\n            $timepicker.hide(true);\n            return;\n          }\n\n          // Navigate with keyboard\n          var newDate = new Date($timepicker.$date);\n          var hours = newDate.getHours();\n          var hoursLength = formatDate(newDate, hoursFormat).length;\n          var minutes = newDate.getMinutes();\n          var minutesLength = formatDate(newDate, minutesFormat).length;\n          var seconds = newDate.getSeconds();\n          var 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          if ((!isTouch && element.attr('readonly')) || element.attr('disabled')) return;\n          _show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function () {\n            if ($timepicker.$element) $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n            if (options.keyboard) {\n              if (element) element.on('keydown', $timepicker.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var _hide = $timepicker.hide;\n        $timepicker.hide = function (blur) {\n          if (!$timepicker.$isShown) return;\n          if ($timepicker.$element) $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n          if (options.keyboard) {\n            if (element) element.off('keydown', $timepicker.$onKeyDown);\n          }\n          _hide(blur);\n        };\n\n        return $timepicker;\n\n      }\n\n      timepickerFactory.defaults = defaults;\n      return timepickerFactory;\n\n    };\n\n  })\n\n\n  .directive('bsTimepicker', function ($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n    var defaults = $timepicker.defaults;\n    var isNative = /(ip[ao]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 = {\n          scope: scope\n        };\n        angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'autoclose', 'timeType', 'timeFormat', 'timezone', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'secondStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'roundDisplay', 'id', 'prefixClass', 'prefixEvent', 'defaultDate'], 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\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\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        // Visibility binding support\n        if (attr.bsShow) {\n          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            if (newValue === true) {\n              timepicker.show();\n            } else {\n              timepicker.hide();\n            }\n          });\n        }\n\n        // Initialize parser\n        var dateParser = $dateParser({\n          format: options.timeFormat,\n          lang: lang\n        });\n\n        // Observe attributes for changes\n        angular.forEach(['minTime', 'maxTime'], function (key) {\n          // console.warn('attr.$observe(%s)', key, attr[key]);\n          if (angular.isDefined(attr[key])) {\n            attr.$observe(key, function (newValue) {\n              timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n              if (!isNaN(timepicker.$options[key])) timepicker.$build();\n              validateAgainstMinMaxTime(controller.$dateValue);\n            });\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 undefined;\n          }\n          validateAgainstMinMaxTime(parsedTime);\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          }\n          return new Date(date);\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        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        } 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: 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      templateUrl: 'select/select.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      multiple: false,\n      allNoneButtons: false,\n      sort: true,\n      caretHtml: '&nbsp;<span class=\"caret\"></span>',\n      placeholder: 'Choose among the following...',\n      allText: 'All',\n      noneText: 'None',\n      maxLength: 3,\n      maxLengthHtml: 'selected',\n      iconCheckmark: 'glyphicon glyphicon-ok',\n      toggle: false\n    };\n\n    this.$get = function ($window, $document, $rootScope, $tooltip, $timeout) {\n\n      // var bodyEl = angular.element($window.document.body);\n      var isNative = /(ip[ao]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        } 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            if ($select.$isActive(index)) {\n              scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1);\n            } else {\n              scope.$activeIndex.push(index);\n            }\n            if (options.sort) scope.$activeIndex.sort(function (a, b) { return a - b; }); // use numeric sort instead of default sort\n          } else {\n            scope.$activeIndex = index;\n          }\n          return scope.$activeIndex;\n        };\n\n        $select.select = function (index) {\n          if (angular.isUndefined(index) || index < 0 || index >= scope.$matches.length) { return; }\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                if (angular.isUndefined(scope.$matches[index])) {\n                  return null;\n                }\n                return scope.$matches[index].value;\n              }));\n            } else {\n              if (options.toggle) {\n                controller.$setViewValue((value === controller.$modelValue) ? undefined : value);\n              } else {\n                controller.$setViewValue(value);\n              }\n              // Hide if single select\n              $select.hide();\n            }\n          });\n          // Emit event\n          scope.$emit(options.prefixEvent + '.select', value, index, $select);\n          if (angular.isDefined(options.onSelect) && angular.isFunction(options.onSelect)) {\n            options.onSelect(value, index, $select);\n          }\n        };\n\n        // Protected methods\n\n        $select.$updateActiveIndex = function () {\n          if (options.multiple) {\n            if (angular.isArray(controller.$modelValue)) {\n              scope.$activeIndex = controller.$modelValue.map(function (value) {\n                return $select.$getIndex(value);\n              });\n            } else {\n              scope.$activeIndex = [];\n            }\n          } else {\n            if (angular.isDefined(controller.$modelValue) && scope.$matches.length) {\n              scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n            } else {\n              scope.$activeIndex = -1;\n            }\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          }\n          return scope.$activeIndex === index;\n        };\n\n        $select.$getIndex = function (value) {\n          var index;\n          for (index = scope.$matches.length; index--;) {\n            if (angular.equals(scope.$matches[index].value, value)) break;\n          }\n          return index;\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            var anchor;\n\n            if (evt.target.nodeName !== 'A') {\n              var anchorCandidate = targetEl.parent();\n              while (!anchor && anchorCandidate.length > 0) {\n                if (anchorCandidate[0].nodeName === 'A') {\n                  anchor = anchorCandidate;\n                }\n                anchorCandidate = anchorCandidate.parent();\n              }\n            }\n\n            if (anchor) {\n              angular.element(anchor).triggerHandler('click');\n            } else {\n              targetEl.triggerHandler('click');\n            }\n          }\n        };\n\n        $select.$onKeyDown = function (evt) {\n          if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n          // Let tab propagate\n          if (evt.keyCode !== 9) {\n            evt.preventDefault();\n            evt.stopPropagation();\n          }\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        $select.$isIE = function () {\n          var ua = $window.navigator.userAgent;\n          return ua.indexOf('MSIE ') > 0 || ua.indexOf('Trident/') > 0 || ua.indexOf('Edge/') > 0;\n        };\n\n        $select.$selectScrollFix = function (e) {\n          if ($document[0].activeElement.tagName === 'UL') {\n            e.preventDefault();\n            e.stopImmediatePropagation();\n            e.target.focus();\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 && angular.isUndefined(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(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'placeholder', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id', 'sort', 'caretHtml', 'prefixClass', 'prefixEvent', 'toggle'], 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\n        // bind functions from the attrs to the show, hide and select events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide', 'onSelect'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\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\n        // Add support for select markup\n        if (element[0].nodeName.toLowerCase() === 'select') {\n          var inputEl = element;\n          inputEl.css('display', 'none');\n          element = angular.element('<button type=\"button\" class=\"btn btn-default\"></button>');\n          inputEl.after(element);\n        }\n\n        // Build proper bsOptions\n        var parsedOptions = $parseOptions(attr.bsOptions);\n\n        // Initialize select\n        var select = $select(element, controller, options);\n\n        if (select.$isIE()) {\n          element[0].addEventListener('blur', select.$selectScrollFix);\n        }\n\n        // Watch bsOptions values before filtering for changes\n        var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n        scope.$watch(watchedOptions, function (newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n          parsedOptions.valuesFn(scope, controller)\n          .then(function (values) {\n            select.update(values);\n            controller.$render();\n          });\n        }, true);\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function (newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n          select.$updateActiveIndex();\n          controller.$render();\n        }, true);\n\n        // Model rendering in view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          var selected;\n          var index;\n          if (options.multiple && angular.isArray(controller.$modelValue)) {\n            selected = controller.$modelValue.map(function (value) {\n              index = select.$getIndex(value);\n              return index !== -1 ? 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 = index !== -1 ? select.$scope.$matches[index].label : false;\n          }\n          element.html((selected || options.placeholder) + (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: 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;\n        var unbindIncludeContentLoaded;\n        var trackedElements = $scrollspy.$trackedElements = [];\n        var sortedElements = [];\n        var activeTarget;\n        var debouncedCheckPosition;\n        var throttledCheckPosition;\n        var debouncedCheckOffsets;\n        /* eslint-disable no-unused-vars */\n        var viewportHeight;\n        /* eslint-enable no-unused-vars */\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.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: 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      templateUrl: '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        var popover;\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'customClass', 'autoClose', 'id', 'prefixClass', 'prefixEvent', 'bsEnabled'], 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])) options[key] = false;\n        });\n\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\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\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function (key) {\n          if (attr[key]) {\n            attr.$observe(key, function (newValue, oldValue) {\n              scope[key] = $sce.trustAsHtml(newValue);\n              if (angular.isDefined(oldValue)) {\n                requestAnimationFrame(function () {\n                  if (popover) popover.$applyPlacement();\n                });\n              }\n            });\n          }\n        });\n\n        // Support scope as an object\n        if (attr.bsPopover) {\n          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            if (angular.isDefined(oldValue)) {\n              requestAnimationFrame(function () {\n                if (popover) popover.$applyPlacement();\n              });\n            }\n          }, true);\n        }\n\n        // Visibility binding support\n        if (attr.bsShow) {\n          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            if (newValue === true) {\n              popover.show();\n            } else {\n              popover.hide();\n            }\n          });\n        }\n\n        // Enabled binding support\n        if (attr.bsEnabled) {\n          scope.$watch(attr.bsEnabled, function (newValue) {\n            if (!popover || !angular.isDefined(newValue)) return;\n            if (angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(popover),?/i);\n            if (newValue === false) {\n              popover.setEnabled(false);\n            } else {\n              popover.setEnabled(true);\n            }\n          });\n        }\n\n        // Viewport support\n        if (attr.viewport) {\n          scope.$watch(attr.viewport, function (newValue) {\n            if (!popover || !angular.isDefined(newValue)) return;\n            popover.setViewport(newValue);\n          });\n        }\n\n        // Initialize popover\n        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: 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: modal/modal.js\nangular.module('mgcrea.ngStrap.modal', ['mgcrea.ngStrap.core', 'mgcrea.ngStrap.helpers.dimensions'])\n\n  .provider('$modal', function () {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      backdropAnimation: 'am-fade',\n      customClass: '',\n      prefixClass: 'modal',\n      prefixEvent: 'modal',\n      placement: 'top',\n      templateUrl: 'modal/modal.tpl.html',\n      template: '',\n      contentTemplate: false,\n      container: false,\n      element: null,\n      backdrop: true,\n      keyboard: true,\n      html: false,\n      show: true,\n      size: null,\n      zIndex: null\n    };\n\n    this.$get = function ($window, $rootScope, $bsCompiler, $animate, $timeout, $sce, dimensions) {\n\n      var forEach = angular.forEach;\n      var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n      var bodyElement = angular.element($window.document.body);\n\n      var backdropCount = 0;\n      var dialogBaseZindex = 1050;\n      var backdropBaseZindex = 1040;\n\n      var validSizes = {\n        lg: 'modal-lg',\n        sm: 'modal-sm'\n      };\n\n      function ModalFactory (config) {\n\n        var $modal = {};\n\n        // Common vars\n        var options = $modal.$options = angular.extend({}, defaults, config);\n        var promise = $modal.$promise = $bsCompiler.compile(options);\n        var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n        if (!options.element && !options.container) {\n          options.container = 'body';\n        }\n\n        if (options.zIndex) {\n          dialogBaseZindex = parseInt(options.zIndex, 10);\n          backdropBaseZindex = dialogBaseZindex - 10;\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        // Fetch, compile then initialize modal\n        var compileData;\n        var modalElement;\n        var modalScope;\n        var backdropElement = angular.element('<div class=\"' + options.prefixClass + '-backdrop\"/>');\n        backdropElement.css({position: 'fixed', top: '0px', left: '0px', bottom: '0px', right: '0px'});\n        promise.then(function (data) {\n          compileData = data;\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          destroyModalElement();\n\n          // remove backdrop element\n          if (backdropElement) {\n            backdropElement.remove();\n            backdropElement = null;\n          }\n\n          // Destroy scope\n          scope.$destroy();\n        };\n\n        $modal.show = function () {\n          if ($modal.$isShown) return;\n\n          var parent;\n          var 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          // destroy any existing modal elements\n          if (modalElement) destroyModalElement();\n\n          // create a new scope, so we can destroy it and all child scopes\n          // when destroying the modal element\n          modalScope = $modal.$scope.$new();\n          // Fetch a cloned element linked from template (noop callback is required)\n          modalElement = $modal.$element = compileData.link(modalScope, function (clonedElement, scope) {});\n\n          if (options.backdrop) {\n            // set z-index\n            modalElement.css({'z-index': dialogBaseZindex + (backdropCount * 20)});\n            backdropElement.css({'z-index': backdropBaseZindex + (backdropCount * 20)});\n\n            // increment number of backdrops\n            backdropCount++;\n          }\n\n          if (scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n            return;\n          }\n          if (angular.isDefined(options.onBeforeShow) && angular.isFunction(options.onBeforeShow)) {\n            options.onBeforeShow($modal);\n          }\n\n          // Set the initial positioning.\n          modalElement.css({display: 'block'}).addClass(options.placement);\n\n          // Options: customClass\n          if (options.customClass) {\n            modalElement.addClass(options.customClass);\n          }\n\n          // Options: size\n          if (options.size && validSizes[options.size]) {\n            angular.element(findElement('.modal-dialog', modalElement[0])).addClass(validSizes[options.size]);\n          }\n\n          // Options: animation\n          if (options.animation) {\n            if (options.backdrop) {\n              backdropElement.addClass(options.backdropAnimation);\n            }\n            modalElement.addClass(options.animation);\n          }\n\n          if (options.backdrop) {\n            $animate.enter(backdropElement, bodyElement, null);\n          }\n\n          // Support v1.2+ $animate\n          // https://github.com/angular/angular.js/issues/11713\n          if (angular.version.minor <= 2) {\n            $animate.enter(modalElement, parent, after, enterAnimateCallback);\n          } else {\n            $animate.enter(modalElement, parent, after).then(enterAnimateCallback);\n          }\n\n          $modal.$isShown = scope.$isShown = true;\n          safeDigest(scope);\n          // Focus once the enter-animation has started\n          // Weird PhantomJS bug hack\n          var el = modalElement[0];\n          requestAnimationFrame(function () {\n            el.focus();\n          });\n\n          bodyElement.addClass(options.prefixClass + '-open');\n          if (options.animation) {\n            bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n          }\n\n          // Bind events\n          bindBackdropEvents();\n          bindKeyboardEvents();\n        };\n\n        function enterAnimateCallback () {\n          scope.$emit(options.prefixEvent + '.show', $modal);\n          if (angular.isDefined(options.onShow) && angular.isFunction(options.onShow)) {\n            options.onShow($modal);\n          }\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          if (angular.isDefined(options.onBeforeHide) && angular.isFunction(options.onBeforeHide)) {\n            options.onBeforeHide($modal);\n          }\n\n          // Support v1.2+ $animate\n          // https://github.com/angular/angular.js/issues/11713\n          if (angular.version.minor <= 2) {\n            $animate.leave(modalElement, leaveAnimateCallback);\n          } else {\n            $animate.leave(modalElement).then(leaveAnimateCallback);\n          }\n\n          if (options.backdrop) {\n            // decrement number of backdrops\n            backdropCount--;\n            $animate.leave(backdropElement);\n          }\n          $modal.$isShown = scope.$isShown = false;\n          safeDigest(scope);\n\n          // Unbind events\n          unbindBackdropEvents();\n          unbindKeyboardEvents();\n        };\n\n        function leaveAnimateCallback () {\n          scope.$emit(options.prefixEvent + '.hide', $modal);\n          if (angular.isDefined(options.onHide) && angular.isFunction(options.onHide)) {\n            options.onHide($modal);\n          }\n          if (findElement('.modal').length <= 0) {\n            bodyElement.removeClass(options.prefixClass + '-open');\n          }\n          if (options.animation) {\n            bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n          }\n        }\n\n        $modal.toggle = function () {\n          if ($modal.$isShown) {\n            $modal.hide();\n          } else {\n            $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        function bindBackdropEvents () {\n          if (options.backdrop) {\n            modalElement.on('click', hideOnBackdropClick);\n            backdropElement.on('click', hideOnBackdropClick);\n            backdropElement.on('wheel', preventEventDefault);\n          }\n        }\n\n        function unbindBackdropEvents () {\n          if (options.backdrop) {\n            modalElement.off('click', hideOnBackdropClick);\n            backdropElement.off('click', hideOnBackdropClick);\n            backdropElement.off('wheel', preventEventDefault);\n          }\n        }\n\n        function bindKeyboardEvents () {\n          if (options.keyboard) {\n            modalElement.on('keyup', $modal.$onKeyUp);\n          }\n        }\n\n        function unbindKeyboardEvents () {\n          if (options.keyboard) {\n            modalElement.off('keyup', $modal.$onKeyUp);\n          }\n        }\n\n        // Private helpers\n\n        function hideOnBackdropClick (evt) {\n          if (evt.target !== evt.currentTarget) return;\n          if (options.backdrop === 'static') {\n            $modal.focus();\n          } else {\n            $modal.hide();\n          }\n        }\n\n        function preventEventDefault (evt) {\n          evt.preventDefault();\n        }\n\n        function destroyModalElement () {\n          if ($modal.$isShown && modalElement !== null) {\n            // un-bind events\n            unbindBackdropEvents();\n            unbindKeyboardEvents();\n          }\n\n          if (modalScope) {\n            modalScope.$destroy();\n            modalScope = null;\n          }\n\n          if (modalElement) {\n            modalElement.remove();\n            modalElement = $modal.$element = null;\n          }\n        }\n\n        return $modal;\n\n      }\n\n      // Helper functions\n\n      function safeDigest (scope) {\n        /* eslint-disable no-unused-expressions */\n        scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n        /* eslint-enable no-unused-expressions */\n      }\n\n      function findElement (query, element) {\n        return angular.element((element || document).querySelectorAll(query));\n      }\n\n      return ModalFactory;\n\n    };\n\n  })\n\n  .directive('bsModal', function ($window, $sce, $parse, $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', 'templateUrl', 'controller', 'controllerAs', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'backdropAnimation', 'id', 'prefixEvent', 'prefixClass', 'customClass', 'modalClass', 'size', 'zIndex'], function (key) {\n          if (angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Options: alias modalClass to customClass\n        if (options.modalClass) {\n          options.customClass = options.modalClass;\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])) options[key] = false;\n        });\n\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function (key) {\n          if (attr[key]) {\n            attr.$observe(key, function (newValue, oldValue) {\n              scope[key] = $sce.trustAsHtml(newValue);\n            });\n          }\n        });\n\n        // Support scope as an object\n        if (attr.bsModal) {\n          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\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: helpers/raf.js\nif (angular.version.minor < 3 && angular.version.dot < 14) {\n  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\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;\n        var displayFn;\n        var valueName;\n        /* eslint-disable no-unused-vars */\n        var keyName;\n        var groupByFn;\n        /* eslint-enable no-unused-vars */\n        var valueFn;\n        var 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            if (!angular.isArray(values)) {\n              values = [];\n            }\n            $parseOptions.$values = values.length ? 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 = {};\n            var label;\n            var 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/dimensions.js\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n  .factory('dimensions', function () {\n\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      var curLeft;\n      var curCSSTop;\n      var curTop;\n      var curOffset;\n      var curCSSLeft;\n      var calculatePosition;\n      var position = fn.css(element, 'position');\n      var curElem = angular.element(element);\n      var 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      var offsetParentEl;\n      var 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* offsetParentEl\n        offsetParentEl = offsetParentElement(element);\n\n        // Get correct offsets\n        offset = fn.offset(element);\n        if (!nodeName(offsetParentEl, 'html')) {\n          offsetParentRect = fn.offset(offsetParentEl);\n        }\n\n        // Add offsetParent borders\n        offsetParentRect.top += fn.css(offsetParentEl, 'borderTopWidth', true);\n        offsetParentRect.left += fn.css(offsetParentEl, '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    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/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      var args = arguments;\n      var 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    if (!options) options = {};\n    return function () {\n      var context = this;\n      var 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/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;\n    var str = value.toString().toLowerCase();\n    for (var i = 0; i < len; i++) {\n      if (array[i].toLowerCase() === str) { return i; }\n    }\n    return -1; // Return -1 per the \"Array.indexOf()\" method.\n  }\n\n  var defaults = this.defaults = {\n    format: 'shortDate',\n    strict: false\n  };\n\n  this.$get = function ($locale, dateFilter) {\n\n    var DateParserFactory = function (config) {\n\n      var options = angular.extend({}, defaults, config);\n\n      var $dateParser = {};\n\n      /* eslint-disable key-spacing, quote-props */\n      var regExpMap = {\n        'sss'   : '[0-9]{3}',\n        'ss'    : '[0-5][0-9]',\n        's'     : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n        'mm'    : '[0-5][0-9]',\n        'm'     : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n        'HH'    : '[01][0-9]|2[0-3]',\n        'H'     : options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]',\n        'hh'    : '[0][1-9]|[1][012]',\n        'h'     : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n        'a'     : 'AM|PM',\n        'EEEE'  : $locale.DATETIME_FORMATS.DAY.join('|'),\n        'EEE'   : $locale.DATETIME_FORMATS.SHORTDAY.join('|'),\n        'dd'    : '0[1-9]|[12][0-9]|3[01]',\n        'd'     : options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]',\n        'MMMM'  : $locale.DATETIME_FORMATS.MONTH.join('|'),\n        'MMM'   : $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n        'MM'    : '0[1-9]|1[012]',\n        'M'     : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n        'yyyy'  : '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',\n        'yy'    : '[0-9]{2}',\n        'y'     : options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}'\n      };\n\n      var setFnMap = {\n        'sss'   : proto.setMilliseconds,\n        'ss'    : proto.setSeconds,\n        's'     : proto.setSeconds,\n        'mm'    : proto.setMinutes,\n        'm'     : proto.setMinutes,\n        'HH'    : proto.setHours,\n        'H'     : proto.setHours,\n        'hh'    : proto.setHours,\n        'h'     : proto.setHours,\n        'EEEE'  : noop,\n        'EEE'   : noop,\n        'dd'    : proto.setDate,\n        'd'     : proto.setDate,\n        'a'     : function (value) { var hours = this.getHours() % 12; return this.setHours(value.match(/pm/i) ? hours + 12 : hours); },\n        'MMMM'  : function (value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.MONTH, value)); },\n        'MMM'   : function (value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.SHORTMONTH, value)); },\n        'MM'    : function (value) { return this.setMonth(1 * value - 1); },\n        'M'     : function (value) { return this.setMonth(1 * value - 1); },\n        'yyyy'  : proto.setFullYear,\n        'yy'    : function (value) { return this.setFullYear(2000 + 1 * value); },\n        'y'     : function (value) { return (1 * value <= 50 && value.length === 2) ? this.setFullYear(2000 + 1 * value) : this.setFullYear(1 * value); }\n      };\n      /* eslint-enable key-spacing, quote-props */\n\n      var regex;\n      var setMap;\n\n      $dateParser.init = function () {\n        $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;\n        regex = regExpForFormat($dateParser.$format);\n        setMap = setMapForFormat($dateParser.$format);\n      };\n\n      $dateParser.isValid = function (date) {\n        if (angular.isDate(date)) return !isNaN(date.getTime());\n        return regex.test(date);\n      };\n\n      $dateParser.parse = function (value, baseDate, format, timezone) {\n        // check for date format special names\n        if (format) format = $locale.DATETIME_FORMATS[format] || format;\n        if (angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format, timezone);\n        var formatRegex = format ? regExpForFormat(format) : regex;\n        var formatSetMap = format ? setMapForFormat(format) : setMap;\n        var matches = formatRegex.exec(value);\n        if (!matches) return false;\n        // use custom ParseDate object to set parsed values\n        var date = baseDate && !isNaN(baseDate.getTime()) ? new ParseDate().fromDate(baseDate) : new ParseDate().fromDate(new Date(1970, 0, 1, 0));\n        for (var i = 0; i < matches.length - 1; i++) {\n          if (formatSetMap[i]) formatSetMap[i].call(date, matches[i + 1]);\n        }\n        // convert back to native Date object\n        var newDate = date.toDate();\n\n        // check new native Date object for day values overflow\n        if (parseInt(date.day, 10) !== newDate.getDate()) {\n          return false;\n        }\n\n        return newDate;\n      };\n\n      $dateParser.getDateForAttribute = function (key, value) {\n        var date;\n\n        if (value === 'today') {\n          var today = new Date();\n          date = new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, (key === 'minDate' ? 0 : -1));\n        } else if (angular.isString(value) && value.match(/^\".+\"$/)) { // Support {{ dateObj }}\n          date = new Date(value.substr(1, value.length - 2));\n        } else if (isNumeric(value)) {\n          date = new Date(parseInt(value, 10));\n        } else if (angular.isString(value) && value.length === 0) { // Reset date\n          date = key === 'minDate' ? -Infinity : +Infinity;\n        } else {\n          date = new Date(value);\n        }\n\n        return date;\n      };\n\n      $dateParser.getTimeForAttribute = function (key, value) {\n        var time;\n\n        if (value === 'now') {\n          time = new Date().setFullYear(1970, 0, 1);\n        } else if (angular.isString(value) && value.match(/^\".+\"$/)) {\n          time = new Date(value.substr(1, value.length - 2)).setFullYear(1970, 0, 1);\n        } else if (isNumeric(value)) {\n          time = new Date(parseInt(value, 10)).setFullYear(1970, 0, 1);\n        } else if (angular.isString(value) && value.length === 0) { // Reset time\n          time = key === 'minTime' ? -Infinity : +Infinity;\n        } else {\n          time = $dateParser.parse(value, new Date(1970, 0, 1, 0));\n        }\n\n        return time;\n      };\n\n      /* Handle switch to/from daylight saving.\n      * Hours may be non-zero on daylight saving cut-over:\n      * > 12 when midnight changeover, but then cannot generate\n      * midnight datetime, so jump to 1AM, otherwise reset.\n      * @param  date  (Date) the date to check\n      * @return  (Date) the corrected date\n      *\n      * __ copied from jquery ui datepicker __\n      */\n      $dateParser.daylightSavingAdjust = function (date) {\n        if (!date) {\n          return null;\n        }\n        date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n        return date;\n      };\n\n      /* Correct the date for timezone offset.\n      * @param  date  (Date) the date to adjust\n      * @param  timezone  (string) the timezone to adjust for\n      * @param  undo  (boolean) to add or subtract timezone offset\n      * @return  (Date) the corrected date\n      */\n      $dateParser.timezoneOffsetAdjust = function (date, timezone, undo) {\n        if (!date) {\n          return null;\n        }\n        // Right now, only 'UTC' is supported.\n        if (timezone && timezone === 'UTC') {\n          date = new Date(date.getTime());\n          date.setMinutes(date.getMinutes() + (undo ? -1 : 1) * date.getTimezoneOffset());\n        }\n        return date;\n      };\n\n      // Private functions\n\n      function regExpForFormat (format) {\n        // `format` string can contain literal values.\n        // These need to be escaped by surrounding with\n        // single quotes (e.g. `\"h 'in the morning'\"`).\n        // In order to output a single quote, escape it - i.e.,\n        // two single quotes in a sequence (e.g. `\"h 'o''clock'\"`).\n\n        var re = buildDateAbstractRegex(format);\n        return buildDateParseRegex(re);\n      }\n\n      function buildDateAbstractRegex (format) {\n        var escapedFormat = escapeReservedSymbols(format);\n        var escapedLiteralFormat = escapedFormat.replace(/''/g, '\\\\\\'');\n        var literalRegex = /('(?:\\\\'|.)*?')/;\n        var formatParts = escapedLiteralFormat.split(literalRegex);\n        var dateElements = Object.keys(regExpMap);\n        var dateRegexParts = [];\n\n        angular.forEach(formatParts, function (part) {\n          if (isFormatStringLiteral(part)) {\n            part = trimLiteralEscapeChars(part);\n          } else {\n            // Abstract replaces to avoid collisions\n            for (var i = 0; i < dateElements.length; i++) {\n              part = part.split(dateElements[i]).join('${' + i + '}');\n            }\n          }\n          dateRegexParts.push(part);\n        });\n\n        return dateRegexParts.join('');\n      }\n\n      function escapeReservedSymbols (text) {\n        return text.replace(/\\\\/g, '[\\\\\\\\]')\n                   .replace(/-/g, '[-]')\n                   .replace(/\\./g, '[.]')\n                   .replace(/\\*/g, '[*]')\n                   .replace(/\\+/g, '[+]')\n                   .replace(/\\?/g, '[?]')\n                   .replace(/\\$/g, '[$]')\n                   .replace(/\\^/g, '[^]')\n                   .replace(/\\//g, '[/]')\n                   .replace(/\\\\s/g, '[\\\\s]');\n      }\n\n      function isFormatStringLiteral (text) {\n        return /^'.*'$/.test(text);\n      }\n\n      function trimLiteralEscapeChars (text) {\n        return text.replace(/^'(.*)'$/, '$1');\n      }\n\n      function buildDateParseRegex (abstractRegex) {\n        var dateElements = Object.keys(regExpMap);\n        var re = abstractRegex;\n\n        // Replace abstracted values\n        for (var i = 0; i < dateElements.length; i++) {\n          re = re.split('${' + i + '}').join('(' + regExpMap[dateElements[i]] + ')');\n        }\n\n        return new RegExp('^' + re + '$', ['i']);\n      }\n\n      function setMapForFormat (format) {\n        var re = buildDateAbstractRegex(format);\n        return buildDateParseValuesMap(re);\n      }\n\n      function buildDateParseValuesMap (abstractRegex) {\n        var dateElements = Object.keys(regExpMap);\n        var valuesRegex = new RegExp('\\\\${(\\\\d+)}', 'g');\n        var valuesMatch;\n        var keyIndex;\n        var valueKey;\n        var valueFunction;\n        var valuesFunctionMap = [];\n\n        /* eslint-disable no-cond-assign */\n        while ((valuesMatch = valuesRegex.exec(abstractRegex)) !== null) {\n          keyIndex = valuesMatch[1];\n          valueKey = dateElements[keyIndex];\n          valueFunction = setFnMap[valueKey];\n\n          valuesFunctionMap.push(valueFunction);\n        }\n\n        return valuesFunctionMap;\n      }\n\n      $dateParser.init();\n      return $dateParser;\n\n    };\n\n    return DateParserFactory;\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/compiler.js\n// NOTICE: This file was forked from the angular-material project (github.com/angular/material)\n// MIT Licensed - Copyright (c) 2014-2015 Google, Inc. http://angularjs.org\n\nangular.module('mgcrea.ngStrap.core', [])\n  .service('$bsCompiler', bsCompilerService);\n\nfunction bsCompilerService ($q, $http, $injector, $compile, $controller, $templateCache) {\n\n  /*\n   * @ngdoc service\n   * @name $bsCompiler\n   * @module material.core\n   * @description\n   * The $bsCompiler service is an abstraction of angular's compiler, that allows the developer\n   * to easily compile an element with a templateUrl, controller, and locals.\n   *\n   * @usage\n   * <hljs lang=\"js\">\n   * $bsCompiler.compile({\n   *   templateUrl: 'modal.html',\n   *   controller: 'ModalCtrl',\n   *   locals: {\n   *     modal: myModalInstance;\n   *   }\n   * }).then(function(compileData) {\n   *   compileData.element; // modal.html's template in an element\n   *   compileData.link(myScope); //attach controller & scope to element\n   * });\n   * </hljs>\n   */\n\n   /*\n    * @ngdoc method\n    * @name $bsCompiler#compile\n    * @description A helper to compile an HTML template/templateUrl with a given controller,\n    * locals, and scope.\n    * @param {object} options An options object, with the following properties:\n    *\n    *    - `controller` - `{(string=|function()=}` Controller fn that should be associated with\n    *      newly created scope or the name of a registered controller if passed as a string.\n    *    - `controllerAs` - `{string=}` A controller alias name. If present the controller will be\n    *      published to scope under the `controllerAs` name.\n    *    - `template` - `{string=}` An html template as a string.\n    *    - `templateUrl` - `{string=}` A path to an html template.\n    *    - `transformTemplate` - `{function(template)=}` A function which transforms the template after\n    *      it is loaded. It will be given the template string as a parameter, and should\n    *      return a a new string representing the transformed template.\n    *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n    *      be injected into the controller. If any of these dependencies are promises, the compiler\n    *      will wait for them all to be resolved, or if one is rejected before the controller is\n    *      instantiated `compile()` will fail..\n    *      * `key` - `{string}`: a name of a dependency to be injected into the controller.\n    *      * `factory` - `{string|function}`: If `string` then it is an alias for a service.\n    *        Otherwise if function, then it is injected and the return value is treated as the\n    *        dependency. If the result is a promise, it is resolved before its value is\n    *        injected into the controller.\n    *\n    * @returns {object=} promise A promise, which will be resolved with a `compileData` object.\n    * `compileData` has the following properties:\n    *\n    *   - `element` - `{element}`: an uncompiled element matching the provided template.\n    *   - `link` - `{function(scope)}`: A link function, which, when called, will compile\n    *     the element and instantiate the provided controller (if given).\n    *   - `locals` - `{object}`: The locals which will be passed into the controller once `link` is\n    *     called. If `bindToController` is true, they will be coppied to the ctrl instead\n    *   - `bindToController` - `bool`: bind the locals to the controller, instead of passing them in.\n    */\n  this.compile = function (options) {\n\n    if (options.template && /\\.html$/.test(options.template)) {\n      console.warn('Deprecated use of `template` option to pass a file. Please use the `templateUrl` option instead.');\n      options.templateUrl = options.template;\n      options.template = '';\n    }\n\n    var templateUrl = options.templateUrl;\n    var template = options.template || '';\n    var controller = options.controller;\n    var controllerAs = options.controllerAs;\n    var resolve = options.resolve || {};\n    var locals = options.locals || {};\n    var transformTemplate = options.transformTemplate || angular.identity;\n    var bindToController = options.bindToController;\n\n    // Take resolve values and invoke them.\n    // Resolves can either be a string (value: 'MyRegisteredAngularConst'),\n    // or an invokable 'factory' of sorts: (value: function ValueGetter($dependency) {})\n    angular.forEach(resolve, function (value, key) {\n      if (angular.isString(value)) {\n        resolve[key] = $injector.get(value);\n      } else {\n        resolve[key] = $injector.invoke(value);\n      }\n    });\n    // Add the locals, which are just straight values to inject\n    // eg locals: { three: 3 }, will inject three into the controller\n    angular.extend(resolve, locals);\n\n    if (template) {\n      resolve.$template = $q.when(template);\n    } else if (templateUrl) {\n      resolve.$template = fetchTemplate(templateUrl);\n    } else {\n      throw new Error('Missing `template` / `templateUrl` option.');\n    }\n\n    if (options.titleTemplate) {\n      resolve.$template = $q.all([resolve.$template, fetchTemplate(options.titleTemplate)])\n        .then(function (templates) {\n          var templateEl = angular.element(templates[0]);\n          findElement('[ng-bind=\"title\"]', templateEl[0])\n            .removeAttr('ng-bind')\n            .html(templates[1]);\n          return templateEl[0].outerHTML;\n        });\n    }\n\n    if (options.contentTemplate) {\n      // TODO(mgcrea): deprecate?\n      resolve.$template = $q.all([resolve.$template, fetchTemplate(options.contentTemplate)])\n        .then(function (templates) {\n          var templateEl = angular.element(templates[0]);\n          var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0])\n            .removeAttr('ng-bind')\n            .html(templates[1]);\n          // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n          if (!options.templateUrl) contentEl.next().remove();\n          return templateEl[0].outerHTML;\n        });\n    }\n\n    // Wait for all the resolves to finish if they are promises\n    return $q.all(resolve).then(function (locals) {\n\n      var template = transformTemplate(locals.$template);\n      if (options.html) {\n        template = template.replace(/ng-bind=\"/ig, 'ng-bind-html=\"');\n      }\n      // var element = options.element || angular.element('<div>').html(template.trim()).contents();\n      var element = angular.element('<div>').html(template.trim()).contents();\n      var linkFn = $compile(element);\n\n      // Return a linking function that can be used later when the element is ready\n      return {\n        locals: locals,\n        element: element,\n        link: function link (scope) {\n          locals.$scope = scope;\n\n          // Instantiate controller if it exists, because we have scope\n          if (controller) {\n            var invokeCtrl = $controller(controller, locals, true);\n            if (bindToController) {\n              angular.extend(invokeCtrl.instance, locals);\n            }\n            // Support angular@~1.2 invokeCtrl\n            var ctrl = angular.isObject(invokeCtrl) ? invokeCtrl : invokeCtrl();\n            // See angular-route source for this logic\n            element.data('$ngControllerController', ctrl);\n            element.children().data('$ngControllerController', ctrl);\n\n            if (controllerAs) {\n              scope[controllerAs] = ctrl;\n            }\n          }\n\n          return linkFn.apply(null, arguments);\n        }\n      };\n    });\n\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})\n      .then(function (res) {\n        return res.data;\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      templateUrl: '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            if (options.keyboard && $dropdown.$element) $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n            bodyEl.on('click', onBodyClick);\n          }, 0, false);\n          if (parentEl.hasClass('dropdown')) parentEl.addClass('open');\n        };\n\n        var hide = $dropdown.hide;\n        $dropdown.hide = function () {\n          if (!$dropdown.$isShown) return;\n          if (options.keyboard && $dropdown.$element) $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n          bodyEl.off('click', onBodyClick);\n          if (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      compile: function (tElement, tAttrs) {\n\n        // Support for inlined template (next sibling)\n        // It must be fetched before compilation\n        if (!tAttrs.bsDropdown) {\n          var nextSibling = tElement[0].nextSibling;\n          while (nextSibling && nextSibling.nodeType !== 1) {\n            nextSibling = nextSibling.nextSibling;\n          }\n          if (nextSibling && nextSibling.className.split(' ').indexOf('dropdown-menu') >= 0) {\n            tAttrs.template = nextSibling.outerHTML;\n            tAttrs.templateUrl = undefined;\n            nextSibling.parentNode.removeChild(nextSibling);\n          }\n        }\n\n        return function postLink (scope, element, attr) {\n\n          // Directive options\n          var options = {scope: scope};\n          angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'id', 'autoClose'], function (key) {\n            if (angular.isDefined(tAttrs[key])) options[key] = tAttrs[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])) options[key] = false;\n          });\n\n          // bind functions from the attrs to the show and hide events\n          angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n            var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n            if (angular.isDefined(attr[bsKey])) {\n              options[key] = scope.$eval(attr[bsKey]);\n            }\n          });\n\n          // Support scope as an object\n          if (attr.bsDropdown) {\n            scope.$watch(attr.bsDropdown, function (newValue, oldValue) {\n              scope.content = newValue;\n            }, true);\n          }\n\n          // Initialize dropdown\n          var dropdown = $dropdown(element, options);\n\n          // Visibility binding support\n          if (attr.bsShow) {\n            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              if (newValue === true) {\n                dropdown.show();\n              } else {\n                dropdown.hide();\n              }\n            });\n          }\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\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        }\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 = !!controller.$viewValue;\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            controller.$render();\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          if (typeof v !== 'boolean' && constantValueRegExp.test(v)) {\n            value = scope.$eval(v);\n          } else {\n            value = v;\n          }\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.$viewValue, 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: 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      templateUrl: '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      hasToday: false,\n      hasClear: false,\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 isNative = /(ip[ao]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        scope.$hasToday = options.hasToday;\n        scope.$hasClear = options.hasClear;\n        var $picker = $datepicker.$views[scope.$mode];\n\n        // Scope methods\n\n        scope.$select = function (date, disabled) {\n          if (disabled) return;\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        scope.$setToday = function () {\n          if (options.autoclose) {\n            $datepicker.setMode(0);\n            $datepicker.select(new Date());\n          } else {\n            $datepicker.select(new Date(), true);\n          }\n        };\n        scope.$clear = function () {\n          if (options.autoclose) {\n            $datepicker.setMode(0);\n            $datepicker.select(null);\n          } else {\n            $datepicker.select(null, true);\n          }\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(date)) {\n            if (!angular.isDate(controller.$dateValue) || isNaN(controller.$dateValue.getTime())) {\n              controller.$dateValue = new Date(date);\n            }\n          } else {\n            controller.$dateValue = null;\n          }\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              $datepicker.hide(true);\n            } else {\n              scope.$apply(function () { $datepicker.setMode(scope.$mode - 1); });\n            }\n            return;\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          if ((!isTouch && element.attr('readonly')) || element.attr('disabled')) return;\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[ao]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};\n        angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'autoclose', 'dateType', 'dateFormat', 'timezone', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id', 'prefixClass', 'prefixEvent', 'hasToday', 'hasClear'], 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', 'hasToday', 'hasClear'], function (key) {\n          if (angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) {\n            options[key] = false;\n          }\n        });\n\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\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        // Visibility binding support\n        if (attr.bsShow) {\n          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            if (newValue === true) {\n              datepicker.show();\n            } else {\n              datepicker.hide();\n            }\n          });\n        }\n\n        // Observe attributes for changes\n        angular.forEach(['minDate', 'maxDate'], function (key) {\n          // console.warn('attr.$observe(%s)', key, attr[key]);\n          if (angular.isDefined(attr[key])) {\n            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              if (!isNaN(datepicker.$options[key])) datepicker.$build(false);\n              validateAgainstMinMaxDate(controller.$dateValue);\n            });\n          }\n        });\n\n        // Observe date format\n        if (angular.isDefined(attr.dateFormat)) {\n          attr.$observe('dateFormat', function (newValue) {\n            datepicker.$options.dateFormat = newValue;\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          }\n          validateAgainstMinMaxDate(parsedDate);\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          }\n          return new Date(date);\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function (modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var date;\n          if (angular.isUndefined(modelValue) || modelValue === null) {\n            date = NaN;\n          } else if (angular.isDate(modelValue)) {\n            date = modelValue;\n          } else if (options.dateType === 'string') {\n            date = dateParser.parse(modelValue, null, options.modelDateFormat);\n          } else if (options.dateType === 'unix') {\n            date = new Date(modelValue * 1000);\n          } else {\n            date = new Date(modelValue);\n          }\n          // Setup default value?\n          // if (isNaN(date.getTime())) {\n          //   var today = new Date();\n          //   date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n          // }\n          controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n          return getDateFormattedString();\n        });\n\n        // viewValue -> element\n        controller.$render = function () {\n          // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n          element.val(getDateFormattedString());\n        };\n\n        function getDateFormattedString () {\n          return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n        }\n\n        // Garbage collection\n        scope.$on('$destroy', function () {\n          if (datepicker) datepicker.destroy();\n          options = null;\n          datepicker = null;\n        });\n\n      }\n    };\n\n  })\n\n  .provider('datepickerViews', function () {\n\n    // var defaults = this.defaults = {\n    //   dayFormat: 'dd',\n    //   daySplit: 7\n    // };\n\n    // Split array into smaller arrays\n    function split (arr, size) {\n      var arrays = [];\n      while (arr.length > 0) {\n        arrays.push(arr.splice(0, size));\n      }\n      return arrays;\n    }\n\n    // Modulus operator\n    function mod (n, m) {\n      return ((n % m) + m) % m;\n    }\n\n    this.$get = function ($dateFormatter, $dateParser, $sce) {\n\n      return function (picker) {\n\n        var scope = picker.$scope;\n        var options = picker.$options;\n\n        var lang = options.lang;\n        var formatDate = function (date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n        var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n        var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n        var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n        var weekDaysLabelsHtml = $sce.trustAsHtml('<th class=\"dow text-center\">' + weekDaysLabels.join('</th><th class=\"dow text-center\">') + '</th>');\n\n        var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n        var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n\n        var views = [{\n          format: options.dayFormat,\n          split: 7,\n          steps: {month: 1},\n          update: function (date, force) {\n            if (!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n              angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n              picker.$build();\n            } else if (date.getDate() !== viewDate.date || date.getDate() === 1) {\n                // chaging picker current month will cause viewDate.date to be set to first day of the month,\n                // in $datepicker.$selectPane, so picker would not update selected day display if\n                // user picks first day of the new month.\n                // As a workaround, we are always forcing update when picked date is first day of month.\n              viewDate.date = picker.$date.getDate();\n              picker.$updateSelected();\n            }\n          },\n          build: function () {\n            var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1);\n            var firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n            var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5);\n            var 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 = [];\n            var 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            scope.isTodayDisabled = this.isDisabled(new Date());\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 = [];\n            var 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 = [];\n            var 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            var 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: 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\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        } else if (!self.$options.disallowToggle && isActive(value)) {\n          deactivateItem(value);\n        } else {\n          activateItem(value);\n        }\n\n        self.$viewChangeListeners.forEach(function (fn) {\n          fn();\n        });\n      };\n\n      self.$activeIndexes = function () {\n        if (self.$options.allowMultiple) {\n          return self.$targets.$active;\n        }\n        return 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;\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    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            } 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              } 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          if (!attrs.disabled) {\n            var index = attrs.bsCollapseToggle && attrs.bsCollapseToggle !== 'bs-collapse-toggle' ? attrs.bsCollapseToggle : bsCollapseCtrl.$toggles.indexOf(element);\n            bsCollapseCtrl.$setActive(index * 1);\n            scope.$apply();\n          }\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          } 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: 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      templateUrl: '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    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', 'templateUrl', 'controller', 'controllerAs', '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])) options[key] = false;\n        });\n\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function (key) {\n          if (attr[key]) {\n            attr.$observe(key, function (newValue, oldValue) {\n              scope[key] = $sce.trustAsHtml(newValue);\n            });\n          }\n        });\n\n        // Support scope as an object\n        if (attr.bsAside) {\n          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\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: alert/alert.js\n// @BUG: following snippet won't compile correctly\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      templateUrl: '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    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', 'templateUrl', 'controller', 'controllerAs', '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])) options[key] = false;\n        });\n\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\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          if (attr[key]) {\n            attr.$observe(key, function (newValue, oldValue) {\n              scope[key] = $sce.trustAsHtml(newValue);\n            });\n          }\n        });\n\n        // Support scope as an object\n        if (attr.bsAlert) {\n          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\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: 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      setWidth: 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        var setWidth = false;\n        var initialAffixTop = 0;\n        var initialOffsetTop = 0;\n        var offsetTop = 0;\n        var offsetBottom = 0;\n        var affixed = null;\n        var 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          } 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 = options.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          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            } 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          // Add proper affix class\n          element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\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[0].style.position;\n          var initialTop = element[0].style.top;\n          // Reset position to calculate correct offsetTop\n          if (options.inlineStyles) {\n            element.css('position', (options.offsetParent) ? '' : 'relative');\n            element.css('top', '');\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              } else {\n                offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\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            } 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            element.css('top', initialTop);\n          }\n        };\n\n        // Private methods\n\n        function getRequiredAffixClass (_unpin, position, elementHeight) {\n          var scrollTop = getScrollTop();\n          var scrollHeight = getScrollHeight();\n\n          if (scrollTop <= offsetTop) {\n            return 'top';\n          } else if (_unpin !== null) {\n            return scrollTop + _unpin <= position.top ? 'middle' : 'bottom';\n          } else if (offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n            return 'bottom';\n          }\n          return 'middle';\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, $timeout) {\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', 'setWidth'], 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;\n        $timeout(function () { affix = $affix(element, options); });\n        scope.$on('$destroy', function () {\n          if (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: 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})(window, document);\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      templateUrl: 'typeahead/typeahead.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      minLength: 1,\n      filter: 'bsAsyncFilter',\n      limit: 6,\n      autoSelect: false,\n      comparator: '',\n      trimValue: true\n    };\n\n    this.$get = function ($window, $rootScope, $tooltip, $$rAF, $timeout) {\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          // wrap in a $timeout so the results are updated\n          // before repositioning\n          safeDigest(scope);\n          $$rAF($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          if (angular.isDefined(options.onSelect) && angular.isFunction(options.onSelect)) {\n            options.onSelect(value, index, $typeahead);\n          }\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 index;\n          for (index = scope.$matches.length; index--;) {\n            if (angular.equals(scope.$matches[index].value, value)) break;\n          }\n          return index;\n        };\n\n        $typeahead.$onMouseDown = function (evt) {\n          // Prevent blur on mousedown\n          evt.preventDefault();\n          evt.stopPropagation();\n        };\n\n        $typeahead.$$updateScrollTop = function (container, index) {\n          if (index > -1 && index < container.children.length) {\n            var active = container.children[index];\n            var clientTop = active.offsetTop;\n            var clientBottom = active.offsetTop + active.clientHeight;\n            var highWatermark = container.scrollTop;\n            var lowWatermark = container.scrollTop + container.clientHeight;\n\n            // active entry overlaps top border\n            if (clientBottom >= highWatermark && clientTop < highWatermark) {\n              container.scrollTop = Math.max(0, container.scrollTop - container.clientHeight);\n            } else if (clientBottom > lowWatermark) {\n              // top of active element is invisible because it's below the bottom of the visible container window\n              container.scrollTop = clientTop;\n            }\n          }\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          // Navigate with keyboard\n          } else if (evt.keyCode === 38 && scope.$activeIndex > 0) {\n            scope.$activeIndex--;\n          } else if (evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) {\n            scope.$activeIndex++;\n          } else if (angular.isUndefined(scope.$activeIndex)) {\n            scope.$activeIndex = 0;\n          }\n\n          // update scrollTop property on $typeahead when scope.$activeIndex is not in visible area\n          $typeahead.$$updateScrollTop($typeahead.$element[0], scope.$activeIndex);\n          scope.$digest();\n        };\n\n        // Overrides\n\n        var show = $typeahead.show;\n        $typeahead.show = function () {\n          show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed immediately.\n          $timeout(function () {\n            if ($typeahead.$element) {\n              $typeahead.$element.on('mousedown', $typeahead.$onMouseDown);\n              if (options.keyboard) {\n                if (element) element.on('keydown', $typeahead.$onKeyDown);\n              }\n            }\n          }, 0, false);\n        };\n\n        var hide = $typeahead.hide;\n        $typeahead.hide = function () {\n          if ($typeahead.$element) $typeahead.$element.off('mousedown', $typeahead.$onMouseDown);\n          if (options.keyboard) {\n            if (element) element.off('keydown', $typeahead.$onKeyDown);\n          }\n          if (!options.autoSelect) {\n            $typeahead.activate(-1);\n          }\n          hide();\n        };\n\n        return $typeahead;\n\n      }\n\n      // Helper functions\n\n      function safeDigest (scope) {\n        /* eslint-disable no-unused-expressions */\n        scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n        /* eslint-enable no-unused-expressions */\n      }\n\n      TypeaheadFactory.defaults = defaults;\n      return TypeaheadFactory;\n\n    };\n\n  })\n\n  .filter('bsAsyncFilter', function ($filter) {\n    return function (array, expression, comparator) {\n      if (array && angular.isFunction(array.then)) {\n        return array.then(function (results) {\n          return $filter('filter')(results, expression, comparator);\n        });\n      }\n      return $filter('filter')(array, expression, comparator);\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        // Fixes firefox bug when using objects in model with typeahead\n        // Yes this breaks any other directive using a 'change' event on this input,\n        // but if it is using the 'change' event why is it used with typeahead?\n        element.off('change');\n\n        // Directive options\n        var options = {\n          scope: scope\n        };\n        angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', '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', 'filter'], function (key) {\n          if (angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) options[key] = false;\n        });\n\n        // bind functions from the attrs to the show, hide and select events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide', 'onSelect'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\n        });\n\n        // Disable browser autocompletion\n        if (!element.attr('autocomplete')) element.attr('autocomplete', 'off');\n\n        // Build proper bsOptions\n        var filter = angular.isDefined(options.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) {\n          bsOptions += ' | ' + filter + ':$viewValue';\n          if (comparator) bsOptions += ':' + comparator;\n        }\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              typeahead.update(values);\n              // Queue a new rendering that will leverage collection loading\n              controller.$render();\n            });\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function (modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var displayValue = parsedOptions.displayValue(modelValue);\n\n          // If we can determine the displayValue, use that\n          if (displayValue) {\n            return displayValue;\n          }\n\n          // If there's no display value, attempt to use the modelValue.\n          // If the model is an object not much we can do\n          if (angular.isDefined(modelValue) && typeof modelValue !== 'object') {\n            return modelValue;\n          }\n          return '';\n        });\n\n        // Model rendering in view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          if (controller.$isEmpty(controller.$viewValue)) {\n            return element.val('');\n          }\n          var index = typeahead.$getIndex(controller.$modelValue);\n          var selected = index !== -1 ? 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          var ss = element[0].selectionStart;\n          var sd = element[0].selectionEnd;\n          element.val(options.trimValue === false ? value : value.trim());\n          element[0].setSelectionRange(ss, sd);\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","'use strict';\n\n// NOTICE: This file was forked from the angular-material project (github.com/angular/material)\n// MIT Licensed - Copyright (c) 2014-2015 Google, Inc. http://angularjs.org\n\nangular.module('mgcrea.ngStrap.core', [])\n  .service('$bsCompiler', bsCompilerService);\n\nfunction bsCompilerService ($q, $http, $injector, $compile, $controller, $templateCache) {\n\n  /*\n   * @ngdoc service\n   * @name $bsCompiler\n   * @module material.core\n   * @description\n   * The $bsCompiler service is an abstraction of angular's compiler, that allows the developer\n   * to easily compile an element with a templateUrl, controller, and locals.\n   *\n   * @usage\n   * <hljs lang=\"js\">\n   * $bsCompiler.compile({\n   *   templateUrl: 'modal.html',\n   *   controller: 'ModalCtrl',\n   *   locals: {\n   *     modal: myModalInstance;\n   *   }\n   * }).then(function(compileData) {\n   *   compileData.element; // modal.html's template in an element\n   *   compileData.link(myScope); //attach controller & scope to element\n   * });\n   * </hljs>\n   */\n\n   /*\n    * @ngdoc method\n    * @name $bsCompiler#compile\n    * @description A helper to compile an HTML template/templateUrl with a given controller,\n    * locals, and scope.\n    * @param {object} options An options object, with the following properties:\n    *\n    *    - `controller` - `{(string=|function()=}` Controller fn that should be associated with\n    *      newly created scope or the name of a registered controller if passed as a string.\n    *    - `controllerAs` - `{string=}` A controller alias name. If present the controller will be\n    *      published to scope under the `controllerAs` name.\n    *    - `template` - `{string=}` An html template as a string.\n    *    - `templateUrl` - `{string=}` A path to an html template.\n    *    - `transformTemplate` - `{function(template)=}` A function which transforms the template after\n    *      it is loaded. It will be given the template string as a parameter, and should\n    *      return a a new string representing the transformed template.\n    *    - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should\n    *      be injected into the controller. If any of these dependencies are promises, the compiler\n    *      will wait for them all to be resolved, or if one is rejected before the controller is\n    *      instantiated `compile()` will fail..\n    *      * `key` - `{string}`: a name of a dependency to be injected into the controller.\n    *      * `factory` - `{string|function}`: If `string` then it is an alias for a service.\n    *        Otherwise if function, then it is injected and the return value is treated as the\n    *        dependency. If the result is a promise, it is resolved before its value is\n    *        injected into the controller.\n    *\n    * @returns {object=} promise A promise, which will be resolved with a `compileData` object.\n    * `compileData` has the following properties:\n    *\n    *   - `element` - `{element}`: an uncompiled element matching the provided template.\n    *   - `link` - `{function(scope)}`: A link function, which, when called, will compile\n    *     the element and instantiate the provided controller (if given).\n    *   - `locals` - `{object}`: The locals which will be passed into the controller once `link` is\n    *     called. If `bindToController` is true, they will be coppied to the ctrl instead\n    *   - `bindToController` - `bool`: bind the locals to the controller, instead of passing them in.\n    */\n  this.compile = function (options) {\n\n    if (options.template && /\\.html$/.test(options.template)) {\n      console.warn('Deprecated use of `template` option to pass a file. Please use the `templateUrl` option instead.');\n      options.templateUrl = options.template;\n      options.template = '';\n    }\n\n    var templateUrl = options.templateUrl;\n    var template = options.template || '';\n    var controller = options.controller;\n    var controllerAs = options.controllerAs;\n    var resolve = options.resolve || {};\n    var locals = options.locals || {};\n    var transformTemplate = options.transformTemplate || angular.identity;\n    var bindToController = options.bindToController;\n\n    // Take resolve values and invoke them.\n    // Resolves can either be a string (value: 'MyRegisteredAngularConst'),\n    // or an invokable 'factory' of sorts: (value: function ValueGetter($dependency) {})\n    angular.forEach(resolve, function (value, key) {\n      if (angular.isString(value)) {\n        resolve[key] = $injector.get(value);\n      } else {\n        resolve[key] = $injector.invoke(value);\n      }\n    });\n    // Add the locals, which are just straight values to inject\n    // eg locals: { three: 3 }, will inject three into the controller\n    angular.extend(resolve, locals);\n\n    if (template) {\n      resolve.$template = $q.when(template);\n    } else if (templateUrl) {\n      resolve.$template = fetchTemplate(templateUrl);\n    } else {\n      throw new Error('Missing `template` / `templateUrl` option.');\n    }\n\n    if (options.titleTemplate) {\n      resolve.$template = $q.all([resolve.$template, fetchTemplate(options.titleTemplate)])\n        .then(function (templates) {\n          var templateEl = angular.element(templates[0]);\n          findElement('[ng-bind=\"title\"]', templateEl[0])\n            .removeAttr('ng-bind')\n            .html(templates[1]);\n          return templateEl[0].outerHTML;\n        });\n    }\n\n    if (options.contentTemplate) {\n      // TODO(mgcrea): deprecate?\n      resolve.$template = $q.all([resolve.$template, fetchTemplate(options.contentTemplate)])\n        .then(function (templates) {\n          var templateEl = angular.element(templates[0]);\n          var contentEl = findElement('[ng-bind=\"content\"]', templateEl[0])\n            .removeAttr('ng-bind')\n            .html(templates[1]);\n          // Drop the default footer as you probably don't want it if you use a custom contentTemplate\n          if (!options.templateUrl) contentEl.next().remove();\n          return templateEl[0].outerHTML;\n        });\n    }\n\n    // Wait for all the resolves to finish if they are promises\n    return $q.all(resolve).then(function (locals) {\n\n      var template = transformTemplate(locals.$template);\n      if (options.html) {\n        template = template.replace(/ng-bind=\"/ig, 'ng-bind-html=\"');\n      }\n      // var element = options.element || angular.element('<div>').html(template.trim()).contents();\n      var element = angular.element('<div>').html(template.trim()).contents();\n      var linkFn = $compile(element);\n\n      // Return a linking function that can be used later when the element is ready\n      return {\n        locals: locals,\n        element: element,\n        link: function link (scope) {\n          locals.$scope = scope;\n\n          // Instantiate controller if it exists, because we have scope\n          if (controller) {\n            var invokeCtrl = $controller(controller, locals, true);\n            if (bindToController) {\n              angular.extend(invokeCtrl.instance, locals);\n            }\n            // Support angular@~1.2 invokeCtrl\n            var ctrl = angular.isObject(invokeCtrl) ? invokeCtrl : invokeCtrl();\n            // See angular-route source for this logic\n            element.data('$ngControllerController', ctrl);\n            element.children().data('$ngControllerController', ctrl);\n\n            if (controllerAs) {\n              scope[controllerAs] = ctrl;\n            }\n          }\n\n          return linkFn.apply(null, arguments);\n        }\n      };\n    });\n\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})\n      .then(function (res) {\n        return res.data;\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      templateUrl: '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            if (options.keyboard && $dropdown.$element) $dropdown.$element.on('keydown', $dropdown.$onKeyDown);\n            bodyEl.on('click', onBodyClick);\n          }, 0, false);\n          if (parentEl.hasClass('dropdown')) parentEl.addClass('open');\n        };\n\n        var hide = $dropdown.hide;\n        $dropdown.hide = function () {\n          if (!$dropdown.$isShown) return;\n          if (options.keyboard && $dropdown.$element) $dropdown.$element.off('keydown', $dropdown.$onKeyDown);\n          bodyEl.off('click', onBodyClick);\n          if (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      compile: function (tElement, tAttrs) {\n\n        // Support for inlined template (next sibling)\n        // It must be fetched before compilation\n        if (!tAttrs.bsDropdown) {\n          var nextSibling = tElement[0].nextSibling;\n          while (nextSibling && nextSibling.nodeType !== 1) {\n            nextSibling = nextSibling.nextSibling;\n          }\n          if (nextSibling && nextSibling.className.split(' ').indexOf('dropdown-menu') >= 0) {\n            tAttrs.template = nextSibling.outerHTML;\n            tAttrs.templateUrl = undefined;\n            nextSibling.parentNode.removeChild(nextSibling);\n          }\n        }\n\n        return function postLink (scope, element, attr) {\n\n          // Directive options\n          var options = {scope: scope};\n          angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'id', 'autoClose'], function (key) {\n            if (angular.isDefined(tAttrs[key])) options[key] = tAttrs[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])) options[key] = false;\n          });\n\n          // bind functions from the attrs to the show and hide events\n          angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n            var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n            if (angular.isDefined(attr[bsKey])) {\n              options[key] = scope.$eval(attr[bsKey]);\n            }\n          });\n\n          // Support scope as an object\n          if (attr.bsDropdown) {\n            scope.$watch(attr.bsDropdown, function (newValue, oldValue) {\n              scope.content = newValue;\n            }, true);\n          }\n\n          // Initialize dropdown\n          var dropdown = $dropdown(element, options);\n\n          // Visibility binding support\n          if (attr.bsShow) {\n            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              if (newValue === true) {\n                dropdown.show();\n              } else {\n                dropdown.hide();\n              }\n            });\n          }\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","'use strict';\n\nangular.module('mgcrea.ngStrap.tooltip', ['mgcrea.ngStrap.core', '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      templateUrl: 'tooltip/tooltip.tpl.html',\n      template: '',\n      titleTemplate: 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      mouseDownPreventDefault: true,\n      mouseDownStopPropagation: true,\n      viewport: {\n        selector: 'body',\n        padding: 0\n      }\n    };\n\n    this.$get = function ($window, $rootScope, $bsCompiler, $q, $templateCache, $http, $animate, $sce, dimensions, $$rAF, $timeout) {\n\n      var isNative = /(ip[ao]d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n      var $body = angular.element($window.document);\n\n      function TooltipFactory (element, config) {\n\n        var $tooltip = {};\n\n        // Common vars\n        var options = $tooltip.$options = angular.extend({}, defaults, config);\n        var promise = $tooltip.$promise = $bsCompiler.compile(options);\n        var scope = $tooltip.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n        var nodeName = element[0].nodeName.toLowerCase();\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;\n        var hoverState;\n\n        // Fetch, compile then initialize tooltip\n        var compileData;\n        var tipElement;\n        var tipContainer;\n        var tipScope;\n        promise.then(function (data) {\n          compileData = data;\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              if (options.trigger === 'focus') {\n                element[0].focus();\n              } else {\n                $tooltip.show();\n              }\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          if (angular.isDefined(options.onBeforeShow) && angular.isFunction(options.onBeforeShow)) {\n            options.onBeforeShow($tooltip);\n          }\n          var parent;\n          var 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 = compileData.link(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          if (after) {\n            after.after(tipElement);\n          } else {\n            parent.prepend(tipElement);\n          }\n\n          $tooltip.$isShown = scope.$isShown = true;\n          safeDigest(scope);\n\n          // Now, apply placement\n          $tooltip.$applyPlacement();\n\n          // Once placed, animate it.\n          // Support v1.2+ $animate\n          // https://github.com/angular/angular.js/issues/11713\n          if (angular.version.minor <= 2) {\n            $animate.enter(tipElement, parent, after, enterAnimateCallback);\n          } else {\n            $animate.enter(tipElement, parent, after).then(enterAnimateCallback);\n          }\n          safeDigest(scope);\n\n          $$rAF(function () {\n            // Once the tooltip is placed and the animation starts, make the tooltip visible\n            if (tipElement) tipElement.css({visibility: 'visible'});\n\n            // Bind events\n            if (options.keyboard) {\n              if (options.trigger !== 'focus') {\n                $tooltip.focus();\n              }\n              bindKeyboardEvents();\n            }\n          });\n\n          if (options.autoClose) {\n            bindAutoCloseEvents();\n          }\n\n        };\n\n        function enterAnimateCallback () {\n          scope.$emit(options.prefixEvent + '.show', $tooltip);\n          if (angular.isDefined(options.onShow) && angular.isFunction(options.onShow)) {\n            options.onShow($tooltip);\n          }\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          if (angular.isDefined(options.onBeforeHide) && angular.isFunction(options.onBeforeHide)) {\n            options.onBeforeHide($tooltip);\n          }\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          if (tipElement !== null) {\n            // Support v1.2+ $animate\n            // https://github.com/angular/angular.js/issues/11713\n            if (angular.version.minor <= 2) {\n              $animate.leave(tipElement, leaveAnimateCallback);\n            } else {\n              $animate.leave(tipElement).then(leaveAnimateCallback);\n            }\n          }\n\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          if (angular.isDefined(options.onHide) && angular.isFunction(options.onHide)) {\n            options.onHide($tooltip);\n          }\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 (evt) {\n          if (evt) { evt.preventDefault(); }\n          if ($tooltip.$isShown) {\n            $tooltip.leave();\n          } else {\n            $tooltip.enter();\n          }\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          var autoToken = /\\s?auto?\\s?/i;\n          var 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          var tipWidth = tipElement.prop('offsetWidth');\n          var tipHeight = tipElement.prop('offsetHeight');\n\n          // Refresh viewport position\n          $tooltip.$viewport = options.viewport && findElement(options.viewport.selector || options.viewport);\n\n          // If we're auto placing, we need to check the positioning\n          if (autoPlace) {\n            var originalPlacement = placement;\n            var viewportPosition = getPosition($tooltip.$viewport);\n\n            if (/bottom/.test(originalPlacement) && elementPosition.bottom + tipHeight > viewportPosition.bottom) {\n              placement = originalPlacement.replace('bottom', 'top');\n            } else if (/top/.test(originalPlacement) && elementPosition.top - tipHeight < viewportPosition.top) {\n              placement = originalPlacement.replace('top', 'bottom');\n            }\n\n            if (/left/.test(originalPlacement) && elementPosition.left - tipWidth < viewportPosition.left) {\n              placement = placement.replace('left', 'right');\n            } else if (/right/.test(originalPlacement) && elementPosition.right + tipWidth > viewportPosition.width) {\n              placement = 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          if (options.mouseDownPreventDefault) { evt.preventDefault(); }\n          if (options.mouseDownStopPropagation) { evt.stopPropagation(); }\n          // Some browsers do not auto-focus buttons (eg. Safari)\n          if ($tooltip.$isShown) {\n            element[0].blur();\n          } else {\n            element[0].focus();\n          }\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' || trigger === 'contextmenu') {\n              element.on(trigger, $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              if (nodeName === 'button' && trigger !== 'hover') {\n                element.on(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n              }\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' || trigger === 'contextmenu') {\n              element.off(trigger, $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              if (nodeName === 'button' && trigger !== 'hover') {\n                element.off(isTouch ? 'touchstart' : 'mousedown', $tooltip.$onFocusElementMouseDown);\n              }\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          var 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          /* eslint-disable guard-for-in */\n          for (var p in elRect) { // eslint-disable-line\n            // DO NOT use hasOwnProperty when inspecting the return of getBoundingClientRect.\n            rect[p] = elRect[p];\n          }\n          /* eslint-enable guard-for-in */\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          var scroll = {scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.prop('scrollTop') || 0};\n          var 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                break;\n              default:\n                break;\n            }\n          } else if (split[0] === 'left' || split[0] === 'right') {\n            switch (split[1]) {\n              case 'top':\n                offset.top = position.top - actualHeight + position.height;\n                break;\n              case 'bottom':\n                offset.top = position.top;\n                break;\n              default:\n                break;\n            }\n          }\n\n          return offset;\n        }\n\n        function applyPlacement (offset, placement) {\n          var tip = tipElement[0];\n          var width = tip.offsetWidth;\n          var height = tip.offsetHeight;\n\n          // manually read margins because getBoundingClientRect includes difference\n          var marginTop = parseInt(dimensions.css(tip, 'margin-top'), 10);\n          var 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          var 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            var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight;\n            var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight';\n\n            replaceArrow(arrowDelta, tip[arrowOffsetPosition], isVertical);\n          }\n        }\n\n        // @source https://github.com/twbs/bootstrap/blob/v3.3.5/js/tooltip.js#L380\n        function getViewportAdjustedDelta (placement, position, actualWidth, actualHeight) {\n          var delta = {top: 0, left: 0};\n          if (!$tooltip.$viewport) return delta;\n\n          var viewportPadding = options.viewport && options.viewport.padding || 0;\n          var viewportDimensions = getPosition($tooltip.$viewport);\n\n          if (/right|left/.test(placement)) {\n            var topEdgeOffset = position.top - viewportPadding - viewportDimensions.scroll;\n            var 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            var rightEdgeOffset = position.left + viewportPadding + actualWidth;\n            if (leftEdgeOffset < viewportDimensions.left) { // left overflow\n              delta.left = viewportDimensions.left - leftEdgeOffset;\n            } else if (rightEdgeOffset > viewportDimensions.right) { // 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        /* eslint-disable no-unused-expressions */\n        scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n        /* eslint-enable no-unused-expressions */\n      }\n\n      function findElement (query, element) {\n        return angular.element((element || document).querySelectorAll(query));\n      }\n\n      return TooltipFactory;\n\n    };\n\n  })\n\n  .directive('bsTooltip', function ($window, $location, $sce, $parse, $tooltip, $$rAF) {\n\n    return {\n      restrict: 'EAC',\n      scope: true,\n      link: function postLink (scope, element, attr, transclusion) {\n\n        var tooltip;\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'titleTemplate', '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\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\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\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            if (angular.isDefined(oldValue)) {\n              $$rAF(function () {\n                if (tooltip) tooltip.$applyPlacement();\n              });\n            }\n          }\n        });\n\n        attr.$observe('disabled', function (newValue) {\n          if (newValue && tooltip.$isShown) {\n            tooltip.hide();\n          }\n        });\n\n        // Support scope as an object\n        if (attr.bsTooltip) {\n          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            if (angular.isDefined(oldValue)) {\n              $$rAF(function () {\n                if (tooltip) tooltip.$applyPlacement();\n              });\n            }\n          }, true);\n        }\n\n        // Visibility binding support\n        if (attr.bsShow) {\n          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            if (newValue === true) {\n              tooltip.show();\n            } else {\n              tooltip.hide();\n            }\n          });\n        }\n\n        // Enabled binding support\n        if (attr.bsEnabled) {\n          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            if (newValue === false) {\n              tooltip.setEnabled(false);\n            } else {\n              tooltip.setEnabled(true);\n            }\n          });\n        }\n\n        // Viewport support\n        if (attr.viewport) {\n          scope.$watch(attr.viewport, function (newValue) {\n            if (!tooltip || !angular.isDefined(newValue)) return;\n            tooltip.setViewport(newValue);\n          });\n        }\n\n        // Initialize popover\n        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.timepicker', ['mgcrea.ngStrap.helpers.dateParser', 'mgcrea.ngStrap.helpers.dateFormatter', 'mgcrea.ngStrap.tooltip'])\n\n  .provider('$timepicker', function () {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      defaultDate: 'auto',\n      // uncommenting the following line will break backwards compatability\n      // prefixEvent: 'timepicker',\n      prefixClass: 'timepicker',\n      placement: 'bottom-left',\n      templateUrl: '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 isNative = /(ip[ao]d|iphone|android)/ig.test($window.navigator.userAgent);\n      var isTouch = ('createTouch' in $window.document) && isNative;\n      if (!defaults.lang) {\n        defaults.lang = $dateFormatter.getDefaultLocale();\n      }\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          // 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 = {\n          hour: startDate.getHours(),\n          meridian: startDate.getHours() < 12,\n          minute: startDate.getMinutes(),\n          second: startDate.getSeconds(),\n          millisecond: startDate.getMilliseconds()\n        };\n\n        var format = $dateFormatter.getDatetimeFormat(options.timeFormat, lang);\n\n        var hoursFormat = $dateFormatter.hoursFormat(format);\n        var timeSeparator = $dateFormatter.timeSeparator(format);\n        var minutesFormat = $dateFormatter.minutesFormat(format);\n        var secondsFormat = $dateFormatter.secondsFormat(format);\n        var showSeconds = $dateFormatter.showSeconds(format);\n        var 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, {\n              hour: date.getHours(),\n              minute: date.getMinutes(),\n              second: date.getSeconds(),\n              millisecond: date.getMilliseconds()\n            });\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())) {\n            controller.$dateValue = options.defaultDate === 'today' ? new Date() : new Date(1970, 0, 1);\n          }\n\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 () {\n              $timepicker.hide(true);\n            });\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;\n          var midIndex = scope.midIndex = parseInt(options.length / 2, 10);\n          var hours = [];\n          var 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({\n              date: hour,\n              label: formatDate(hour, hoursFormat),\n              selected: $timepicker.$date && $timepicker.$isSelected(hour, 0),\n              disabled: $timepicker.$isDisabled(hour, 0)\n            });\n          }\n          var minutes = [];\n          var 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({\n              date: minute,\n              label: formatDate(minute, minutesFormat),\n              selected: $timepicker.$date && $timepicker.$isSelected(minute, 1),\n              disabled: $timepicker.$isDisabled(minute, 1)\n            });\n          }\n          var seconds = [];\n          var 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({\n              date: second,\n              label: formatDate(second, secondsFormat),\n              selected: $timepicker.$date && $timepicker.$isSelected(second, 2),\n              disabled: $timepicker.$isDisabled(second, 2)\n            });\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 || startDate);\n          var hours = newDate.getHours();\n          var minutes = newDate.getMinutes();\n          var seconds = newDate.getSeconds();\n          if (index === 0) {\n            newDate.setHours(hours - (parseInt(options.hourStep, 10) * value));\n          } else if (index === 1) {\n            newDate.setMinutes(minutes - (parseInt(options.minuteStep, 10) * value));\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, {\n              hour: targetDate.getHours()\n            });\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, {\n              minute: targetDate.getMinutes()\n            });\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, {\n              second: targetDate.getSeconds()\n            });\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) {\n            $timepicker.hide(true);\n            return;\n          }\n\n          // Navigate with keyboard\n          var newDate = new Date($timepicker.$date);\n          var hours = newDate.getHours();\n          var hoursLength = formatDate(newDate, hoursFormat).length;\n          var minutes = newDate.getMinutes();\n          var minutesLength = formatDate(newDate, minutesFormat).length;\n          var seconds = newDate.getSeconds();\n          var 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          if ((!isTouch && element.attr('readonly')) || element.attr('disabled')) return;\n          _show();\n          // use timeout to hookup the events to prevent\n          // event bubbling from being processed imediately.\n          $timeout(function () {\n            if ($timepicker.$element) $timepicker.$element.on(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n            if (options.keyboard) {\n              if (element) element.on('keydown', $timepicker.$onKeyDown);\n            }\n          }, 0, false);\n        };\n\n        var _hide = $timepicker.hide;\n        $timepicker.hide = function (blur) {\n          if (!$timepicker.$isShown) return;\n          if ($timepicker.$element) $timepicker.$element.off(isTouch ? 'touchstart' : 'mousedown', $timepicker.$onMouseDown);\n          if (options.keyboard) {\n            if (element) element.off('keydown', $timepicker.$onKeyDown);\n          }\n          _hide(blur);\n        };\n\n        return $timepicker;\n\n      }\n\n      timepickerFactory.defaults = defaults;\n      return timepickerFactory;\n\n    };\n\n  })\n\n\n  .directive('bsTimepicker', function ($window, $parse, $q, $dateFormatter, $dateParser, $timepicker) {\n\n    var defaults = $timepicker.defaults;\n    var isNative = /(ip[ao]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 = {\n          scope: scope\n        };\n        angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'autoclose', 'timeType', 'timeFormat', 'timezone', 'modelTimeFormat', 'useNative', 'hourStep', 'minuteStep', 'secondStep', 'length', 'arrowBehavior', 'iconUp', 'iconDown', 'roundDisplay', 'id', 'prefixClass', 'prefixEvent', 'defaultDate'], 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\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\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        // Visibility binding support\n        if (attr.bsShow) {\n          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            if (newValue === true) {\n              timepicker.show();\n            } else {\n              timepicker.hide();\n            }\n          });\n        }\n\n        // Initialize parser\n        var dateParser = $dateParser({\n          format: options.timeFormat,\n          lang: lang\n        });\n\n        // Observe attributes for changes\n        angular.forEach(['minTime', 'maxTime'], function (key) {\n          // console.warn('attr.$observe(%s)', key, attr[key]);\n          if (angular.isDefined(attr[key])) {\n            attr.$observe(key, function (newValue) {\n              timepicker.$options[key] = dateParser.getTimeForAttribute(key, newValue);\n              if (!isNaN(timepicker.$options[key])) timepicker.$build();\n              validateAgainstMinMaxTime(controller.$dateValue);\n            });\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 undefined;\n          }\n          validateAgainstMinMaxTime(parsedTime);\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          }\n          return new Date(date);\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        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        } 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.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      templateUrl: 'select/select.tpl.html',\n      trigger: 'focus',\n      container: false,\n      keyboard: true,\n      html: false,\n      delay: 0,\n      multiple: false,\n      allNoneButtons: false,\n      sort: true,\n      caretHtml: '&nbsp;<span class=\"caret\"></span>',\n      placeholder: 'Choose among the following...',\n      allText: 'All',\n      noneText: 'None',\n      maxLength: 3,\n      maxLengthHtml: 'selected',\n      iconCheckmark: 'glyphicon glyphicon-ok',\n      toggle: false\n    };\n\n    this.$get = function ($window, $document, $rootScope, $tooltip, $timeout) {\n\n      // var bodyEl = angular.element($window.document.body);\n      var isNative = /(ip[ao]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        } 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            if ($select.$isActive(index)) {\n              scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1);\n            } else {\n              scope.$activeIndex.push(index);\n            }\n            if (options.sort) scope.$activeIndex.sort(function (a, b) { return a - b; }); // use numeric sort instead of default sort\n          } else {\n            scope.$activeIndex = index;\n          }\n          return scope.$activeIndex;\n        };\n\n        $select.select = function (index) {\n          if (angular.isUndefined(index) || index < 0 || index >= scope.$matches.length) { return; }\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                if (angular.isUndefined(scope.$matches[index])) {\n                  return null;\n                }\n                return scope.$matches[index].value;\n              }));\n            } else {\n              if (options.toggle) {\n                controller.$setViewValue((value === controller.$modelValue) ? undefined : value);\n              } else {\n                controller.$setViewValue(value);\n              }\n              // Hide if single select\n              $select.hide();\n            }\n          });\n          // Emit event\n          scope.$emit(options.prefixEvent + '.select', value, index, $select);\n          if (angular.isDefined(options.onSelect) && angular.isFunction(options.onSelect)) {\n            options.onSelect(value, index, $select);\n          }\n        };\n\n        // Protected methods\n\n        $select.$updateActiveIndex = function () {\n          if (options.multiple) {\n            if (angular.isArray(controller.$modelValue)) {\n              scope.$activeIndex = controller.$modelValue.map(function (value) {\n                return $select.$getIndex(value);\n              });\n            } else {\n              scope.$activeIndex = [];\n            }\n          } else {\n            if (angular.isDefined(controller.$modelValue) && scope.$matches.length) {\n              scope.$activeIndex = $select.$getIndex(controller.$modelValue);\n            } else {\n              scope.$activeIndex = -1;\n            }\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          }\n          return scope.$activeIndex === index;\n        };\n\n        $select.$getIndex = function (value) {\n          var index;\n          for (index = scope.$matches.length; index--;) {\n            if (angular.equals(scope.$matches[index].value, value)) break;\n          }\n          return index;\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            var anchor;\n\n            if (evt.target.nodeName !== 'A') {\n              var anchorCandidate = targetEl.parent();\n              while (!anchor && anchorCandidate.length > 0) {\n                if (anchorCandidate[0].nodeName === 'A') {\n                  anchor = anchorCandidate;\n                }\n                anchorCandidate = anchorCandidate.parent();\n              }\n            }\n\n            if (anchor) {\n              angular.element(anchor).triggerHandler('click');\n            } else {\n              targetEl.triggerHandler('click');\n            }\n          }\n        };\n\n        $select.$onKeyDown = function (evt) {\n          if (!/(9|13|38|40)/.test(evt.keyCode)) return;\n          // Let tab propagate\n          if (evt.keyCode !== 9) {\n            evt.preventDefault();\n            evt.stopPropagation();\n          }\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        $select.$isIE = function () {\n          var ua = $window.navigator.userAgent;\n          return ua.indexOf('MSIE ') > 0 || ua.indexOf('Trident/') > 0 || ua.indexOf('Edge/') > 0;\n        };\n\n        $select.$selectScrollFix = function (e) {\n          if ($document[0].activeElement.tagName === 'UL') {\n            e.preventDefault();\n            e.stopImmediatePropagation();\n            e.target.focus();\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 && angular.isUndefined(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(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'placeholder', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id', 'sort', 'caretHtml', 'prefixClass', 'prefixEvent', 'toggle'], 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\n        // bind functions from the attrs to the show, hide and select events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide', 'onSelect'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\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\n        // Add support for select markup\n        if (element[0].nodeName.toLowerCase() === 'select') {\n          var inputEl = element;\n          inputEl.css('display', 'none');\n          element = angular.element('<button type=\"button\" class=\"btn btn-default\"></button>');\n          inputEl.after(element);\n        }\n\n        // Build proper bsOptions\n        var parsedOptions = $parseOptions(attr.bsOptions);\n\n        // Initialize select\n        var select = $select(element, controller, options);\n\n        if (select.$isIE()) {\n          element[0].addEventListener('blur', select.$selectScrollFix);\n        }\n\n        // Watch bsOptions values before filtering for changes\n        var watchedOptions = parsedOptions.$match[7].replace(/\\|.+/, '').trim();\n        scope.$watch(watchedOptions, function (newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', watchedOptions, newValue, oldValue);\n          parsedOptions.valuesFn(scope, controller)\n          .then(function (values) {\n            select.update(values);\n            controller.$render();\n          });\n        }, true);\n\n        // Watch model for changes\n        scope.$watch(attr.ngModel, function (newValue, oldValue) {\n          // console.warn('scope.$watch(%s)', attr.ngModel, newValue, oldValue);\n          select.$updateActiveIndex();\n          controller.$render();\n        }, true);\n\n        // Model rendering in view\n        controller.$render = function () {\n          // console.warn('$render', element.attr('ng-model'), 'controller.$modelValue', typeof controller.$modelValue, controller.$modelValue, 'controller.$viewValue', typeof controller.$viewValue, controller.$viewValue);\n          var selected;\n          var index;\n          if (options.multiple && angular.isArray(controller.$modelValue)) {\n            selected = controller.$modelValue.map(function (value) {\n              index = select.$getIndex(value);\n              return index !== -1 ? 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 = index !== -1 ? select.$scope.$matches[index].label : false;\n          }\n          element.html((selected || options.placeholder) + (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.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;\n        var unbindIncludeContentLoaded;\n        var trackedElements = $scrollspy.$trackedElements = [];\n        var sortedElements = [];\n        var activeTarget;\n        var debouncedCheckPosition;\n        var throttledCheckPosition;\n        var debouncedCheckOffsets;\n        /* eslint-disable no-unused-vars */\n        var viewportHeight;\n        /* eslint-enable no-unused-vars */\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.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.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      templateUrl: '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        var popover;\n        // Directive options\n        var options = {scope: scope};\n        angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'customClass', 'autoClose', 'id', 'prefixClass', 'prefixEvent', 'bsEnabled'], 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])) options[key] = false;\n        });\n\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\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\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function (key) {\n          if (attr[key]) {\n            attr.$observe(key, function (newValue, oldValue) {\n              scope[key] = $sce.trustAsHtml(newValue);\n              if (angular.isDefined(oldValue)) {\n                requestAnimationFrame(function () {\n                  if (popover) popover.$applyPlacement();\n                });\n              }\n            });\n          }\n        });\n\n        // Support scope as an object\n        if (attr.bsPopover) {\n          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            if (angular.isDefined(oldValue)) {\n              requestAnimationFrame(function () {\n                if (popover) popover.$applyPlacement();\n              });\n            }\n          }, true);\n        }\n\n        // Visibility binding support\n        if (attr.bsShow) {\n          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            if (newValue === true) {\n              popover.show();\n            } else {\n              popover.hide();\n            }\n          });\n        }\n\n        // Enabled binding support\n        if (attr.bsEnabled) {\n          scope.$watch(attr.bsEnabled, function (newValue) {\n            if (!popover || !angular.isDefined(newValue)) return;\n            if (angular.isString(newValue)) newValue = !!newValue.match(/true|1|,?(popover),?/i);\n            if (newValue === false) {\n              popover.setEnabled(false);\n            } else {\n              popover.setEnabled(true);\n            }\n          });\n        }\n\n        // Viewport support\n        if (attr.viewport) {\n          scope.$watch(attr.viewport, function (newValue) {\n            if (!popover || !angular.isDefined(newValue)) return;\n            popover.setViewport(newValue);\n          });\n        }\n\n        // Initialize popover\n        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.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.modal', ['mgcrea.ngStrap.core', 'mgcrea.ngStrap.helpers.dimensions'])\n\n  .provider('$modal', function () {\n\n    var defaults = this.defaults = {\n      animation: 'am-fade',\n      backdropAnimation: 'am-fade',\n      customClass: '',\n      prefixClass: 'modal',\n      prefixEvent: 'modal',\n      placement: 'top',\n      templateUrl: 'modal/modal.tpl.html',\n      template: '',\n      contentTemplate: false,\n      container: false,\n      element: null,\n      backdrop: true,\n      keyboard: true,\n      html: false,\n      show: true,\n      size: null,\n      zIndex: null\n    };\n\n    this.$get = function ($window, $rootScope, $bsCompiler, $animate, $timeout, $sce, dimensions) {\n\n      var forEach = angular.forEach;\n      var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;\n      var bodyElement = angular.element($window.document.body);\n\n      var backdropCount = 0;\n      var dialogBaseZindex = 1050;\n      var backdropBaseZindex = 1040;\n\n      var validSizes = {\n        lg: 'modal-lg',\n        sm: 'modal-sm'\n      };\n\n      function ModalFactory (config) {\n\n        var $modal = {};\n\n        // Common vars\n        var options = $modal.$options = angular.extend({}, defaults, config);\n        var promise = $modal.$promise = $bsCompiler.compile(options);\n        var scope = $modal.$scope = options.scope && options.scope.$new() || $rootScope.$new();\n\n        if (!options.element && !options.container) {\n          options.container = 'body';\n        }\n\n        if (options.zIndex) {\n          dialogBaseZindex = parseInt(options.zIndex, 10);\n          backdropBaseZindex = dialogBaseZindex - 10;\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        // Fetch, compile then initialize modal\n        var compileData;\n        var modalElement;\n        var modalScope;\n        var backdropElement = angular.element('<div class=\"' + options.prefixClass + '-backdrop\"/>');\n        backdropElement.css({position: 'fixed', top: '0px', left: '0px', bottom: '0px', right: '0px'});\n        promise.then(function (data) {\n          compileData = data;\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          destroyModalElement();\n\n          // remove backdrop element\n          if (backdropElement) {\n            backdropElement.remove();\n            backdropElement = null;\n          }\n\n          // Destroy scope\n          scope.$destroy();\n        };\n\n        $modal.show = function () {\n          if ($modal.$isShown) return;\n\n          var parent;\n          var 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          // destroy any existing modal elements\n          if (modalElement) destroyModalElement();\n\n          // create a new scope, so we can destroy it and all child scopes\n          // when destroying the modal element\n          modalScope = $modal.$scope.$new();\n          // Fetch a cloned element linked from template (noop callback is required)\n          modalElement = $modal.$element = compileData.link(modalScope, function (clonedElement, scope) {});\n\n          if (options.backdrop) {\n            // set z-index\n            modalElement.css({'z-index': dialogBaseZindex + (backdropCount * 20)});\n            backdropElement.css({'z-index': backdropBaseZindex + (backdropCount * 20)});\n\n            // increment number of backdrops\n            backdropCount++;\n          }\n\n          if (scope.$emit(options.prefixEvent + '.show.before', $modal).defaultPrevented) {\n            return;\n          }\n          if (angular.isDefined(options.onBeforeShow) && angular.isFunction(options.onBeforeShow)) {\n            options.onBeforeShow($modal);\n          }\n\n          // Set the initial positioning.\n          modalElement.css({display: 'block'}).addClass(options.placement);\n\n          // Options: customClass\n          if (options.customClass) {\n            modalElement.addClass(options.customClass);\n          }\n\n          // Options: size\n          if (options.size && validSizes[options.size]) {\n            angular.element(findElement('.modal-dialog', modalElement[0])).addClass(validSizes[options.size]);\n          }\n\n          // Options: animation\n          if (options.animation) {\n            if (options.backdrop) {\n              backdropElement.addClass(options.backdropAnimation);\n            }\n            modalElement.addClass(options.animation);\n          }\n\n          if (options.backdrop) {\n            $animate.enter(backdropElement, bodyElement, null);\n          }\n\n          // Support v1.2+ $animate\n          // https://github.com/angular/angular.js/issues/11713\n          if (angular.version.minor <= 2) {\n            $animate.enter(modalElement, parent, after, enterAnimateCallback);\n          } else {\n            $animate.enter(modalElement, parent, after).then(enterAnimateCallback);\n          }\n\n          $modal.$isShown = scope.$isShown = true;\n          safeDigest(scope);\n          // Focus once the enter-animation has started\n          // Weird PhantomJS bug hack\n          var el = modalElement[0];\n          requestAnimationFrame(function () {\n            el.focus();\n          });\n\n          bodyElement.addClass(options.prefixClass + '-open');\n          if (options.animation) {\n            bodyElement.addClass(options.prefixClass + '-with-' + options.animation);\n          }\n\n          // Bind events\n          bindBackdropEvents();\n          bindKeyboardEvents();\n        };\n\n        function enterAnimateCallback () {\n          scope.$emit(options.prefixEvent + '.show', $modal);\n          if (angular.isDefined(options.onShow) && angular.isFunction(options.onShow)) {\n            options.onShow($modal);\n          }\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          if (angular.isDefined(options.onBeforeHide) && angular.isFunction(options.onBeforeHide)) {\n            options.onBeforeHide($modal);\n          }\n\n          // Support v1.2+ $animate\n          // https://github.com/angular/angular.js/issues/11713\n          if (angular.version.minor <= 2) {\n            $animate.leave(modalElement, leaveAnimateCallback);\n          } else {\n            $animate.leave(modalElement).then(leaveAnimateCallback);\n          }\n\n          if (options.backdrop) {\n            // decrement number of backdrops\n            backdropCount--;\n            $animate.leave(backdropElement);\n          }\n          $modal.$isShown = scope.$isShown = false;\n          safeDigest(scope);\n\n          // Unbind events\n          unbindBackdropEvents();\n          unbindKeyboardEvents();\n        };\n\n        function leaveAnimateCallback () {\n          scope.$emit(options.prefixEvent + '.hide', $modal);\n          if (angular.isDefined(options.onHide) && angular.isFunction(options.onHide)) {\n            options.onHide($modal);\n          }\n          if (findElement('.modal').length <= 0) {\n            bodyElement.removeClass(options.prefixClass + '-open');\n          }\n          if (options.animation) {\n            bodyElement.removeClass(options.prefixClass + '-with-' + options.animation);\n          }\n        }\n\n        $modal.toggle = function () {\n          if ($modal.$isShown) {\n            $modal.hide();\n          } else {\n            $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        function bindBackdropEvents () {\n          if (options.backdrop) {\n            modalElement.on('click', hideOnBackdropClick);\n            backdropElement.on('click', hideOnBackdropClick);\n            backdropElement.on('wheel', preventEventDefault);\n          }\n        }\n\n        function unbindBackdropEvents () {\n          if (options.backdrop) {\n            modalElement.off('click', hideOnBackdropClick);\n            backdropElement.off('click', hideOnBackdropClick);\n            backdropElement.off('wheel', preventEventDefault);\n          }\n        }\n\n        function bindKeyboardEvents () {\n          if (options.keyboard) {\n            modalElement.on('keyup', $modal.$onKeyUp);\n          }\n        }\n\n        function unbindKeyboardEvents () {\n          if (options.keyboard) {\n            modalElement.off('keyup', $modal.$onKeyUp);\n          }\n        }\n\n        // Private helpers\n\n        function hideOnBackdropClick (evt) {\n          if (evt.target !== evt.currentTarget) return;\n          if (options.backdrop === 'static') {\n            $modal.focus();\n          } else {\n            $modal.hide();\n          }\n        }\n\n        function preventEventDefault (evt) {\n          evt.preventDefault();\n        }\n\n        function destroyModalElement () {\n          if ($modal.$isShown && modalElement !== null) {\n            // un-bind events\n            unbindBackdropEvents();\n            unbindKeyboardEvents();\n          }\n\n          if (modalScope) {\n            modalScope.$destroy();\n            modalScope = null;\n          }\n\n          if (modalElement) {\n            modalElement.remove();\n            modalElement = $modal.$element = null;\n          }\n        }\n\n        return $modal;\n\n      }\n\n      // Helper functions\n\n      function safeDigest (scope) {\n        /* eslint-disable no-unused-expressions */\n        scope.$$phase || (scope.$root && scope.$root.$$phase) || scope.$digest();\n        /* eslint-enable no-unused-expressions */\n      }\n\n      function findElement (query, element) {\n        return angular.element((element || document).querySelectorAll(query));\n      }\n\n      return ModalFactory;\n\n    };\n\n  })\n\n  .directive('bsModal', function ($window, $sce, $parse, $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', 'templateUrl', 'controller', 'controllerAs', 'contentTemplate', 'placement', 'backdrop', 'keyboard', 'html', 'container', 'animation', 'backdropAnimation', 'id', 'prefixEvent', 'prefixClass', 'customClass', 'modalClass', 'size', 'zIndex'], function (key) {\n          if (angular.isDefined(attr[key])) options[key] = attr[key];\n        });\n\n        // Options: alias modalClass to customClass\n        if (options.modalClass) {\n          options.customClass = options.modalClass;\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])) options[key] = false;\n        });\n\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function (key) {\n          if (attr[key]) {\n            attr.$observe(key, function (newValue, oldValue) {\n              scope[key] = $sce.trustAsHtml(newValue);\n            });\n          }\n        });\n\n        // Support scope as an object\n        if (attr.bsModal) {\n          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\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\nif (angular.version.minor < 3 && angular.version.dot < 14) {\n  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","'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;\n        var displayFn;\n        var valueName;\n        /* eslint-disable no-unused-vars */\n        var keyName;\n        var groupByFn;\n        /* eslint-enable no-unused-vars */\n        var valueFn;\n        var 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            if (!angular.isArray(values)) {\n              values = [];\n            }\n            $parseOptions.$values = values.length ? 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 = {};\n            var label;\n            var 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\nangular.module('mgcrea.ngStrap.helpers.dimensions', [])\n\n  .factory('dimensions', function () {\n\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      var curLeft;\n      var curCSSTop;\n      var curTop;\n      var curOffset;\n      var curCSSLeft;\n      var calculatePosition;\n      var position = fn.css(element, 'position');\n      var curElem = angular.element(element);\n      var 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      var offsetParentEl;\n      var 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* offsetParentEl\n        offsetParentEl = offsetParentElement(element);\n\n        // Get correct offsets\n        offset = fn.offset(element);\n        if (!nodeName(offsetParentEl, 'html')) {\n          offsetParentRect = fn.offset(offsetParentEl);\n        }\n\n        // Add offsetParent borders\n        offsetParentRect.top += fn.css(offsetParentEl, 'borderTopWidth', true);\n        offsetParentRect.left += fn.css(offsetParentEl, '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    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.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      var args = arguments;\n      var 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    if (!options) options = {};\n    return function () {\n      var context = this;\n      var 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","'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;\n    var str = value.toString().toLowerCase();\n    for (var i = 0; i < len; i++) {\n      if (array[i].toLowerCase() === str) { return i; }\n    }\n    return -1; // Return -1 per the \"Array.indexOf()\" method.\n  }\n\n  var defaults = this.defaults = {\n    format: 'shortDate',\n    strict: false\n  };\n\n  this.$get = function ($locale, dateFilter) {\n\n    var DateParserFactory = function (config) {\n\n      var options = angular.extend({}, defaults, config);\n\n      var $dateParser = {};\n\n      /* eslint-disable key-spacing, quote-props */\n      var regExpMap = {\n        'sss'   : '[0-9]{3}',\n        'ss'    : '[0-5][0-9]',\n        's'     : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n        'mm'    : '[0-5][0-9]',\n        'm'     : options.strict ? '[1-5]?[0-9]' : '[0-9]|[0-5][0-9]',\n        'HH'    : '[01][0-9]|2[0-3]',\n        'H'     : options.strict ? '1?[0-9]|2[0-3]' : '[01]?[0-9]|2[0-3]',\n        'hh'    : '[0][1-9]|[1][012]',\n        'h'     : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n        'a'     : 'AM|PM',\n        'EEEE'  : $locale.DATETIME_FORMATS.DAY.join('|'),\n        'EEE'   : $locale.DATETIME_FORMATS.SHORTDAY.join('|'),\n        'dd'    : '0[1-9]|[12][0-9]|3[01]',\n        'd'     : options.strict ? '[1-9]|[1-2][0-9]|3[01]' : '0?[1-9]|[1-2][0-9]|3[01]',\n        'MMMM'  : $locale.DATETIME_FORMATS.MONTH.join('|'),\n        'MMM'   : $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n        'MM'    : '0[1-9]|1[012]',\n        'M'     : options.strict ? '[1-9]|1[012]' : '0?[1-9]|1[012]',\n        'yyyy'  : '[1]{1}[0-9]{3}|[2]{1}[0-9]{3}',\n        'yy'    : '[0-9]{2}',\n        'y'     : options.strict ? '-?(0|[1-9][0-9]{0,3})' : '-?0*[0-9]{1,4}'\n      };\n\n      var setFnMap = {\n        'sss'   : proto.setMilliseconds,\n        'ss'    : proto.setSeconds,\n        's'     : proto.setSeconds,\n        'mm'    : proto.setMinutes,\n        'm'     : proto.setMinutes,\n        'HH'    : proto.setHours,\n        'H'     : proto.setHours,\n        'hh'    : proto.setHours,\n        'h'     : proto.setHours,\n        'EEEE'  : noop,\n        'EEE'   : noop,\n        'dd'    : proto.setDate,\n        'd'     : proto.setDate,\n        'a'     : function (value) { var hours = this.getHours() % 12; return this.setHours(value.match(/pm/i) ? hours + 12 : hours); },\n        'MMMM'  : function (value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.MONTH, value)); },\n        'MMM'   : function (value) { return this.setMonth(indexOfCaseInsensitive($locale.DATETIME_FORMATS.SHORTMONTH, value)); },\n        'MM'    : function (value) { return this.setMonth(1 * value - 1); },\n        'M'     : function (value) { return this.setMonth(1 * value - 1); },\n        'yyyy'  : proto.setFullYear,\n        'yy'    : function (value) { return this.setFullYear(2000 + 1 * value); },\n        'y'     : function (value) { return (1 * value <= 50 && value.length === 2) ? this.setFullYear(2000 + 1 * value) : this.setFullYear(1 * value); }\n      };\n      /* eslint-enable key-spacing, quote-props */\n\n      var regex;\n      var setMap;\n\n      $dateParser.init = function () {\n        $dateParser.$format = $locale.DATETIME_FORMATS[options.format] || options.format;\n        regex = regExpForFormat($dateParser.$format);\n        setMap = setMapForFormat($dateParser.$format);\n      };\n\n      $dateParser.isValid = function (date) {\n        if (angular.isDate(date)) return !isNaN(date.getTime());\n        return regex.test(date);\n      };\n\n      $dateParser.parse = function (value, baseDate, format, timezone) {\n        // check for date format special names\n        if (format) format = $locale.DATETIME_FORMATS[format] || format;\n        if (angular.isDate(value)) value = dateFilter(value, format || $dateParser.$format, timezone);\n        var formatRegex = format ? regExpForFormat(format) : regex;\n        var formatSetMap = format ? setMapForFormat(format) : setMap;\n        var matches = formatRegex.exec(value);\n        if (!matches) return false;\n        // use custom ParseDate object to set parsed values\n        var date = baseDate && !isNaN(baseDate.getTime()) ? new ParseDate().fromDate(baseDate) : new ParseDate().fromDate(new Date(1970, 0, 1, 0));\n        for (var i = 0; i < matches.length - 1; i++) {\n          if (formatSetMap[i]) formatSetMap[i].call(date, matches[i + 1]);\n        }\n        // convert back to native Date object\n        var newDate = date.toDate();\n\n        // check new native Date object for day values overflow\n        if (parseInt(date.day, 10) !== newDate.getDate()) {\n          return false;\n        }\n\n        return newDate;\n      };\n\n      $dateParser.getDateForAttribute = function (key, value) {\n        var date;\n\n        if (value === 'today') {\n          var today = new Date();\n          date = new Date(today.getFullYear(), today.getMonth(), today.getDate() + (key === 'maxDate' ? 1 : 0), 0, 0, 0, (key === 'minDate' ? 0 : -1));\n        } else if (angular.isString(value) && value.match(/^\".+\"$/)) { // Support {{ dateObj }}\n          date = new Date(value.substr(1, value.length - 2));\n        } else if (isNumeric(value)) {\n          date = new Date(parseInt(value, 10));\n        } else if (angular.isString(value) && value.length === 0) { // Reset date\n          date = key === 'minDate' ? -Infinity : +Infinity;\n        } else {\n          date = new Date(value);\n        }\n\n        return date;\n      };\n\n      $dateParser.getTimeForAttribute = function (key, value) {\n        var time;\n\n        if (value === 'now') {\n          time = new Date().setFullYear(1970, 0, 1);\n        } else if (angular.isString(value) && value.match(/^\".+\"$/)) {\n          time = new Date(value.substr(1, value.length - 2)).setFullYear(1970, 0, 1);\n        } else if (isNumeric(value)) {\n          time = new Date(parseInt(value, 10)).setFullYear(1970, 0, 1);\n        } else if (angular.isString(value) && value.length === 0) { // Reset time\n          time = key === 'minTime' ? -Infinity : +Infinity;\n        } else {\n          time = $dateParser.parse(value, new Date(1970, 0, 1, 0));\n        }\n\n        return time;\n      };\n\n      /* Handle switch to/from daylight saving.\n      * Hours may be non-zero on daylight saving cut-over:\n      * > 12 when midnight changeover, but then cannot generate\n      * midnight datetime, so jump to 1AM, otherwise reset.\n      * @param  date  (Date) the date to check\n      * @return  (Date) the corrected date\n      *\n      * __ copied from jquery ui datepicker __\n      */\n      $dateParser.daylightSavingAdjust = function (date) {\n        if (!date) {\n          return null;\n        }\n        date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n        return date;\n      };\n\n      /* Correct the date for timezone offset.\n      * @param  date  (Date) the date to adjust\n      * @param  timezone  (string) the timezone to adjust for\n      * @param  undo  (boolean) to add or subtract timezone offset\n      * @return  (Date) the corrected date\n      */\n      $dateParser.timezoneOffsetAdjust = function (date, timezone, undo) {\n        if (!date) {\n          return null;\n        }\n        // Right now, only 'UTC' is supported.\n        if (timezone && timezone === 'UTC') {\n          date = new Date(date.getTime());\n          date.setMinutes(date.getMinutes() + (undo ? -1 : 1) * date.getTimezoneOffset());\n        }\n        return date;\n      };\n\n      // Private functions\n\n      function regExpForFormat (format) {\n        // `format` string can contain literal values.\n        // These need to be escaped by surrounding with\n        // single quotes (e.g. `\"h 'in the morning'\"`).\n        // In order to output a single quote, escape it - i.e.,\n        // two single quotes in a sequence (e.g. `\"h 'o''clock'\"`).\n\n        var re = buildDateAbstractRegex(format);\n        return buildDateParseRegex(re);\n      }\n\n      function buildDateAbstractRegex (format) {\n        var escapedFormat = escapeReservedSymbols(format);\n        var escapedLiteralFormat = escapedFormat.replace(/''/g, '\\\\\\'');\n        var literalRegex = /('(?:\\\\'|.)*?')/;\n        var formatParts = escapedLiteralFormat.split(literalRegex);\n        var dateElements = Object.keys(regExpMap);\n        var dateRegexParts = [];\n\n        angular.forEach(formatParts, function (part) {\n          if (isFormatStringLiteral(part)) {\n            part = trimLiteralEscapeChars(part);\n          } else {\n            // Abstract replaces to avoid collisions\n            for (var i = 0; i < dateElements.length; i++) {\n              part = part.split(dateElements[i]).join('${' + i + '}');\n            }\n          }\n          dateRegexParts.push(part);\n        });\n\n        return dateRegexParts.join('');\n      }\n\n      function escapeReservedSymbols (text) {\n        return text.replace(/\\\\/g, '[\\\\\\\\]')\n                   .replace(/-/g, '[-]')\n                   .replace(/\\./g, '[.]')\n                   .replace(/\\*/g, '[*]')\n                   .replace(/\\+/g, '[+]')\n                   .replace(/\\?/g, '[?]')\n                   .replace(/\\$/g, '[$]')\n                   .replace(/\\^/g, '[^]')\n                   .replace(/\\//g, '[/]')\n                   .replace(/\\\\s/g, '[\\\\s]');\n      }\n\n      function isFormatStringLiteral (text) {\n        return /^'.*'$/.test(text);\n      }\n\n      function trimLiteralEscapeChars (text) {\n        return text.replace(/^'(.*)'$/, '$1');\n      }\n\n      function buildDateParseRegex (abstractRegex) {\n        var dateElements = Object.keys(regExpMap);\n        var re = abstractRegex;\n\n        // Replace abstracted values\n        for (var i = 0; i < dateElements.length; i++) {\n          re = re.split('${' + i + '}').join('(' + regExpMap[dateElements[i]] + ')');\n        }\n\n        return new RegExp('^' + re + '$', ['i']);\n      }\n\n      function setMapForFormat (format) {\n        var re = buildDateAbstractRegex(format);\n        return buildDateParseValuesMap(re);\n      }\n\n      function buildDateParseValuesMap (abstractRegex) {\n        var dateElements = Object.keys(regExpMap);\n        var valuesRegex = new RegExp('\\\\${(\\\\d+)}', 'g');\n        var valuesMatch;\n        var keyIndex;\n        var valueKey;\n        var valueFunction;\n        var valuesFunctionMap = [];\n\n        /* eslint-disable no-cond-assign */\n        while ((valuesMatch = valuesRegex.exec(abstractRegex)) !== null) {\n          keyIndex = valuesMatch[1];\n          valueKey = dateElements[keyIndex];\n          valueFunction = setFnMap[valueKey];\n\n          valuesFunctionMap.push(valueFunction);\n        }\n\n        return valuesFunctionMap;\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.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.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        }\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 = !!controller.$viewValue;\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            controller.$render();\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          if (typeof v !== 'boolean' && constantValueRegExp.test(v)) {\n            value = scope.$eval(v);\n          } else {\n            value = v;\n          }\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.$viewValue, 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.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      templateUrl: '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      hasToday: false,\n      hasClear: false,\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 isNative = /(ip[ao]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        scope.$hasToday = options.hasToday;\n        scope.$hasClear = options.hasClear;\n        var $picker = $datepicker.$views[scope.$mode];\n\n        // Scope methods\n\n        scope.$select = function (date, disabled) {\n          if (disabled) return;\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        scope.$setToday = function () {\n          if (options.autoclose) {\n            $datepicker.setMode(0);\n            $datepicker.select(new Date());\n          } else {\n            $datepicker.select(new Date(), true);\n          }\n        };\n        scope.$clear = function () {\n          if (options.autoclose) {\n            $datepicker.setMode(0);\n            $datepicker.select(null);\n          } else {\n            $datepicker.select(null, true);\n          }\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(date)) {\n            if (!angular.isDate(controller.$dateValue) || isNaN(controller.$dateValue.getTime())) {\n              controller.$dateValue = new Date(date);\n            }\n          } else {\n            controller.$dateValue = null;\n          }\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              $datepicker.hide(true);\n            } else {\n              scope.$apply(function () { $datepicker.setMode(scope.$mode - 1); });\n            }\n            return;\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          if ((!isTouch && element.attr('readonly')) || element.attr('disabled')) return;\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[ao]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};\n        angular.forEach(['template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay', 'trigger', 'html', 'animation', 'autoclose', 'dateType', 'dateFormat', 'timezone', 'modelDateFormat', 'dayFormat', 'strictFormat', 'startWeek', 'startDate', 'useNative', 'lang', 'startView', 'minView', 'iconLeft', 'iconRight', 'daysOfWeekDisabled', 'id', 'prefixClass', 'prefixEvent', 'hasToday', 'hasClear'], 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', 'hasToday', 'hasClear'], function (key) {\n          if (angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) {\n            options[key] = false;\n          }\n        });\n\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\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        // Visibility binding support\n        if (attr.bsShow) {\n          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            if (newValue === true) {\n              datepicker.show();\n            } else {\n              datepicker.hide();\n            }\n          });\n        }\n\n        // Observe attributes for changes\n        angular.forEach(['minDate', 'maxDate'], function (key) {\n          // console.warn('attr.$observe(%s)', key, attr[key]);\n          if (angular.isDefined(attr[key])) {\n            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              if (!isNaN(datepicker.$options[key])) datepicker.$build(false);\n              validateAgainstMinMaxDate(controller.$dateValue);\n            });\n          }\n        });\n\n        // Observe date format\n        if (angular.isDefined(attr.dateFormat)) {\n          attr.$observe('dateFormat', function (newValue) {\n            datepicker.$options.dateFormat = newValue;\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          }\n          validateAgainstMinMaxDate(parsedDate);\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          }\n          return new Date(date);\n        });\n\n        // modelValue -> $formatters -> viewValue\n        controller.$formatters.push(function (modelValue) {\n          // console.warn('$formatter(\"%s\"): modelValue=%o (%o)', element.attr('ng-model'), modelValue, typeof modelValue);\n          var date;\n          if (angular.isUndefined(modelValue) || modelValue === null) {\n            date = NaN;\n          } else if (angular.isDate(modelValue)) {\n            date = modelValue;\n          } else if (options.dateType === 'string') {\n            date = dateParser.parse(modelValue, null, options.modelDateFormat);\n          } else if (options.dateType === 'unix') {\n            date = new Date(modelValue * 1000);\n          } else {\n            date = new Date(modelValue);\n          }\n          // Setup default value?\n          // if (isNaN(date.getTime())) {\n          //   var today = new Date();\n          //   date = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0);\n          // }\n          controller.$dateValue = dateParser.timezoneOffsetAdjust(date, options.timezone);\n          return getDateFormattedString();\n        });\n\n        // viewValue -> element\n        controller.$render = function () {\n          // console.warn('$render(\"%s\"): viewValue=%o', element.attr('ng-model'), controller.$viewValue);\n          element.val(getDateFormattedString());\n        };\n\n        function getDateFormattedString () {\n          return !controller.$dateValue || isNaN(controller.$dateValue.getTime()) ? '' : formatDate(controller.$dateValue, options.dateFormat);\n        }\n\n        // Garbage collection\n        scope.$on('$destroy', function () {\n          if (datepicker) datepicker.destroy();\n          options = null;\n          datepicker = null;\n        });\n\n      }\n    };\n\n  })\n\n  .provider('datepickerViews', function () {\n\n    // var defaults = this.defaults = {\n    //   dayFormat: 'dd',\n    //   daySplit: 7\n    // };\n\n    // Split array into smaller arrays\n    function split (arr, size) {\n      var arrays = [];\n      while (arr.length > 0) {\n        arrays.push(arr.splice(0, size));\n      }\n      return arrays;\n    }\n\n    // Modulus operator\n    function mod (n, m) {\n      return ((n % m) + m) % m;\n    }\n\n    this.$get = function ($dateFormatter, $dateParser, $sce) {\n\n      return function (picker) {\n\n        var scope = picker.$scope;\n        var options = picker.$options;\n\n        var lang = options.lang;\n        var formatDate = function (date, format) {\n          return $dateFormatter.formatDate(date, format, lang);\n        };\n        var dateParser = $dateParser({format: options.dateFormat, lang: lang, strict: options.strictFormat});\n\n        var weekDaysMin = $dateFormatter.weekdaysShort(lang);\n        var weekDaysLabels = weekDaysMin.slice(options.startWeek).concat(weekDaysMin.slice(0, options.startWeek));\n        var weekDaysLabelsHtml = $sce.trustAsHtml('<th class=\"dow text-center\">' + weekDaysLabels.join('</th><th class=\"dow text-center\">') + '</th>');\n\n        var startDate = picker.$date || (options.startDate ? dateParser.getDateForAttribute('startDate', options.startDate) : new Date());\n        var viewDate = {year: startDate.getFullYear(), month: startDate.getMonth(), date: startDate.getDate()};\n\n        var views = [{\n          format: options.dayFormat,\n          split: 7,\n          steps: {month: 1},\n          update: function (date, force) {\n            if (!this.built || force || date.getFullYear() !== viewDate.year || date.getMonth() !== viewDate.month) {\n              angular.extend(viewDate, {year: picker.$date.getFullYear(), month: picker.$date.getMonth(), date: picker.$date.getDate()});\n              picker.$build();\n            } else if (date.getDate() !== viewDate.date || date.getDate() === 1) {\n                // chaging picker current month will cause viewDate.date to be set to first day of the month,\n                // in $datepicker.$selectPane, so picker would not update selected day display if\n                // user picks first day of the new month.\n                // As a workaround, we are always forcing update when picked date is first day of month.\n              viewDate.date = picker.$date.getDate();\n              picker.$updateSelected();\n            }\n          },\n          build: function () {\n            var firstDayOfMonth = new Date(viewDate.year, viewDate.month, 1);\n            var firstDayOfMonthOffset = firstDayOfMonth.getTimezoneOffset();\n            var firstDate = new Date(+firstDayOfMonth - mod(firstDayOfMonth.getDay() - options.startWeek, 7) * 864e5);\n            var 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 = [];\n            var 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            scope.isTodayDisabled = this.isDisabled(new Date());\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 = [];\n            var 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 = [];\n            var 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            var 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.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\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        } else if (!self.$options.disallowToggle && isActive(value)) {\n          deactivateItem(value);\n        } else {\n          activateItem(value);\n        }\n\n        self.$viewChangeListeners.forEach(function (fn) {\n          fn();\n        });\n      };\n\n      self.$activeIndexes = function () {\n        if (self.$options.allowMultiple) {\n          return self.$targets.$active;\n        }\n        return 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;\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    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            } 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              } 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          if (!attrs.disabled) {\n            var index = attrs.bsCollapseToggle && attrs.bsCollapseToggle !== 'bs-collapse-toggle' ? attrs.bsCollapseToggle : bsCollapseCtrl.$toggles.indexOf(element);\n            bsCollapseCtrl.$setActive(index * 1);\n            scope.$apply();\n          }\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          } 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.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      templateUrl: '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    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', 'templateUrl', 'controller', 'controllerAs', '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])) options[key] = false;\n        });\n\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\n        });\n\n        // Support scope as data-attrs\n        angular.forEach(['title', 'content'], function (key) {\n          if (attr[key]) {\n            attr.$observe(key, function (newValue, oldValue) {\n              scope[key] = $sce.trustAsHtml(newValue);\n            });\n          }\n        });\n\n        // Support scope as an object\n        if (attr.bsAside) {\n          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\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\n// @BUG: following snippet won't compile correctly\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      templateUrl: '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    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', 'templateUrl', 'controller', 'controllerAs', '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])) options[key] = false;\n        });\n\n        // bind functions from the attrs to the show and hide events\n        angular.forEach(['onBeforeShow', 'onShow', 'onBeforeHide', 'onHide'], function (key) {\n          var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);\n          if (angular.isDefined(attr[bsKey])) {\n            options[key] = scope.$eval(attr[bsKey]);\n          }\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          if (attr[key]) {\n            attr.$observe(key, function (newValue, oldValue) {\n              scope[key] = $sce.trustAsHtml(newValue);\n            });\n          }\n        });\n\n        // Support scope as an object\n        if (attr.bsAlert) {\n          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\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.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      setWidth: 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        var setWidth = false;\n        var initialAffixTop = 0;\n        var initialOffsetTop = 0;\n        var offsetTop = 0;\n        var offsetBottom = 0;\n        var affixed = null;\n        var 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          } 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 = options.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          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            } 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          // Add proper affix class\n          element.removeClass(reset).addClass('affix' + ((affix !== 'middle') ? '-' + affix : ''));\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[0].style.position;\n          var initialTop = element[0].style.top;\n          // Reset position to calculate correct offsetTop\n          if (options.inlineStyles) {\n            element.css('position', (options.offsetParent) ? '' : 'relative');\n            element.css('top', '');\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              } else {\n                offsetTop = dimensions.offset(element[0]).top - dimensions.css(element[0], 'marginTop', true) + (options.offsetTop * 1);\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            } 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            element.css('top', initialTop);\n          }\n        };\n\n        // Private methods\n\n        function getRequiredAffixClass (_unpin, position, elementHeight) {\n          var scrollTop = getScrollTop();\n          var scrollHeight = getScrollHeight();\n\n          if (scrollTop <= offsetTop) {\n            return 'top';\n          } else if (_unpin !== null) {\n            return scrollTop + _unpin <= position.top ? 'middle' : 'bottom';\n          } else if (offsetBottom !== null && (position.top + elementHeight + initialAffixTop >= scrollHeight - offsetBottom)) {\n            return 'bottom';\n          }\n          return 'middle';\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, $timeout) {\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', 'setWidth'], 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;\n        $timeout(function () { affix = $affix(element, options); });\n        scope.$on('$destroy', function () {\n          if (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","\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"]}