eventman/static/js/angular-strap.min.js.map

1 satır
No EOL
540 KiB
Text

{"version":3,"sources":["angular-strap.js","typeahead/typeahead.js","helpers/compiler.js","datepicker/datepicker.js","tooltip/tooltip.js","timepicker/timepicker.js","tab/tab.js","scrollspy/scrollspy.js","select/select.js","popover/popover.js","navbar/navbar.js","dropdown/dropdown.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","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","copy","locals","bindToController","angular","forEach","value","isString","$injector","key","invoke","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","keyCode","$digest","show","$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","scrollTop","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","leave","onBeforeHide","autoPlace","autoToken","elementPosition","tipWidth","tipHeight","viewportPosition","originalPlacement","removeClass","tipPosition","getCalculatedOffset","applyPlacement","blur","$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","isUndefined","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","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","active","activeIndex","indexOf","splice","$setActive","name","fn","$pane","$tab","transclude","ngModelCtrl","bsTabsCtrl","attrs","bsActivePane","parsedBsActivePane","assign","$parse","controllers","render","$isActive","spies","debounce","$document","windowEl","bodyEl","throttle","ScrollSpyFactory","scrollEl","isWindowSpy","scrollId","$$count","$scrollspy","unbindViewContentLoaded","unbindIncludeContentLoaded","trackedElements","sortedElements","activeTarget","debouncedCheckOffsets","viewportHeight","debouncedCheckPosition","throttledCheckPosition","checkPositionWithEventLoop","checkOffsets","checkPosition","docEl","$activateElement","offsetTop","setTimeout","activeElement","source","$getTrackedElement","targetElement","querySelector","trackedElement","b","trackElement","toDelete","untrackElement","scrollspy","childEl","child","multiple","allNoneButtons","sort","caretHtml","placeholder","allText","noneText","maxLength","maxLengthHtml","iconCheckmark","SelectFactory","$isMultiple","$showAllNoneButtons","$iconCheckmark","$allText","$activate","$selectNone","$updateActiveIndex","a","$apply","isArray","$getIndex","anchor","anchorCandidate","$selectScrollFix","$isIE","stopImmediatePropagation","ua","tagName","e","dataMultiple","inputEl","addEventListener","join","$isEmpty","content","$popover","PopoverFactory","requestAnimationFrame","bsPopover","popover","routeAttr","$navbar","liElements","li","liElement","pattern","path","RegExp","regexp","matchesSelector","DropdownFactory","$dropdown","onBodyClick","items","parentEl","hasClass","prototype","tAttrs","nextSibling","nodeType","parentNode","removeChild","dropdown","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","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","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","$hasClear","$toggleMode","$views","$mode","setMode","$setToday","$clear","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","$button","constantValueRegExp","isInput","trueValue","falseValue","hasExoticValues","isActive","checked","toggleClass","bind","toggleEvent","v","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.$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 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 // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if (angular.version.minor <= 2) {\n $animate.leave(tipElement, leaveAnimateCallback);\n } else {\n $animate.leave(tipElement).then(leaveAnimateCallback);\n }\n\n $tooltip.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if (options.keyboard && tipElement !== null) {\n unbindKeyboardEvents();\n }\n\n if (options.autoClose && tipElement !== null) {\n unbindAutoCloseEvents();\n }\n };\n\n function leaveAnimateCallback () {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\n 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: 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: 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: 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: 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: 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 = angular.copy(options.resolve || {});\n var locals = angular.copy(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: 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) {\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: 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: 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.$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 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 = angular.copy(options.resolve || {});\n var locals = angular.copy(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.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) {\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.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 // Support v1.2+ $animate\n // https://github.com/angular/angular.js/issues/11713\n if (angular.version.minor <= 2) {\n $animate.leave(tipElement, leaveAnimateCallback);\n } else {\n $animate.leave(tipElement).then(leaveAnimateCallback);\n }\n\n $tooltip.$isShown = scope.$isShown = false;\n safeDigest(scope);\n\n // Unbind events\n if (options.keyboard && tipElement !== null) {\n unbindKeyboardEvents();\n }\n\n if (options.autoClose && tipElement !== null) {\n unbindAutoCloseEvents();\n }\n };\n\n function leaveAnimateCallback () {\n scope.$emit(options.prefixEvent + '.hide', $tooltip);\n 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.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.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.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.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.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.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"]}