and
elements. It is important to note that the state\n * names/globs passed to ui-sref-active shadow the state provided by ui-sref.\n */\n\n/**\n * @ngdoc directive\n * @name ui.router.state.directive:ui-sref-active-eq\n *\n * @requires ui.router.state.$state\n * @requires ui.router.state.$stateParams\n * @requires $interpolate\n *\n * @restrict A\n *\n * @description\n * The same as {@link ui.router.state.directive:ui-sref-active ui-sref-active} but will only activate\n * when the exact target state used in the `ui-sref` is active; no child states.\n *\n */\n$StateRefActiveDirective.$inject = ['$state', '$stateParams', '$interpolate'];\nfunction $StateRefActiveDirective($state, $stateParams, $interpolate) {\n return {\n restrict: \"A\",\n controller: ['$scope', '$element', '$attrs', '$timeout', function ($scope, $element, $attrs, $timeout) {\n var states = [], activeClasses = {}, activeEqClass, uiSrefActive;\n\n // There probably isn't much point in $observing this\n // uiSrefActive and uiSrefActiveEq share the same directive object with some\n // slight difference in logic routing\n activeEqClass = $interpolate($attrs.uiSrefActiveEq || '', false)($scope);\n\n try {\n uiSrefActive = $scope.$eval($attrs.uiSrefActive);\n } catch (e) {\n // Do nothing. uiSrefActive is not a valid expression.\n // Fall back to using $interpolate below\n }\n uiSrefActive = uiSrefActive || $interpolate($attrs.uiSrefActive || '', false)($scope);\n if (isObject(uiSrefActive)) {\n forEach(uiSrefActive, function(stateOrName, activeClass) {\n if (isString(stateOrName)) {\n var ref = parseStateRef(stateOrName, $state.current.name);\n addState(ref.state, $scope.$eval(ref.paramExpr), activeClass);\n }\n });\n }\n\n // Allow uiSref to communicate with uiSrefActive[Equals]\n this.$$addStateInfo = function (newState, newParams) {\n // we already got an explicit state provided by ui-sref-active, so we\n // shadow the one that comes from ui-sref\n if (isObject(uiSrefActive) && states.length > 0) {\n return;\n }\n addState(newState, newParams, uiSrefActive);\n update();\n };\n\n $scope.$on('$stateChangeSuccess', update);\n\n function addState(stateName, stateParams, activeClass) {\n var state = $state.get(stateName, stateContext($element));\n var stateHash = createStateHash(stateName, stateParams);\n\n states.push({\n state: state || { name: stateName },\n params: stateParams,\n hash: stateHash\n });\n\n activeClasses[stateHash] = activeClass;\n }\n\n /**\n * @param {string} state\n * @param {Object|string} [params]\n * @return {string}\n */\n function createStateHash(state, params) {\n if (!isString(state)) {\n throw new Error('state should be a string');\n }\n if (isObject(params)) {\n return state + toJson(params);\n }\n params = $scope.$eval(params);\n if (isObject(params)) {\n return state + toJson(params);\n }\n return state;\n }\n\n // Update route state\n function update() {\n for (var i = 0; i < states.length; i++) {\n if (anyMatch(states[i].state, states[i].params)) {\n addClass($element, activeClasses[states[i].hash]);\n } else {\n removeClass($element, activeClasses[states[i].hash]);\n }\n\n if (exactMatch(states[i].state, states[i].params)) {\n addClass($element, activeEqClass);\n } else {\n removeClass($element, activeEqClass);\n }\n }\n }\n\n function addClass(el, className) { $timeout(function () { el.addClass(className); }); }\n function removeClass(el, className) { el.removeClass(className); }\n function anyMatch(state, params) { return $state.includes(state.name, params); }\n function exactMatch(state, params) { return $state.is(state.name, params); }\n\n update();\n }]\n };\n}\n\nangular.module('ui.router.state')\n .directive('uiSref', $StateRefDirective)\n .directive('uiSrefActive', $StateRefActiveDirective)\n .directive('uiSrefActiveEq', $StateRefActiveDirective)\n .directive('uiState', $StateRefDynamicDirective);\n\n/**\n * @ngdoc filter\n * @name ui.router.state.filter:isState\n *\n * @requires ui.router.state.$state\n *\n * @description\n * Translates to {@link ui.router.state.$state#methods_is $state.is(\"stateName\")}.\n */\n$IsStateFilter.$inject = ['$state'];\nfunction $IsStateFilter($state) {\n var isFilter = function (state, params) {\n return $state.is(state, params);\n };\n isFilter.$stateful = true;\n return isFilter;\n}\n\n/**\n * @ngdoc filter\n * @name ui.router.state.filter:includedByState\n *\n * @requires ui.router.state.$state\n *\n * @description\n * Translates to {@link ui.router.state.$state#methods_includes $state.includes('fullOrPartialStateName')}.\n */\n$IncludedByStateFilter.$inject = ['$state'];\nfunction $IncludedByStateFilter($state) {\n var includesFilter = function (state, params, options) {\n return $state.includes(state, params, options);\n };\n includesFilter.$stateful = true;\n return includesFilter;\n}\n\nangular.module('ui.router.state')\n .filter('isState', $IsStateFilter)\n .filter('includedByState', $IncludedByStateFilter);\n})(window, window.angular);\n/*\n * angular-ui-bootstrap\n * http://angular-ui.github.io/bootstrap/\n\n * Version: 0.14.3 - 2015-10-23\n * License: MIT\n */\nangular.module(\"ui.bootstrap\", [\"ui.bootstrap.tpls\", \"ui.bootstrap.collapse\",\"ui.bootstrap.accordion\",\"ui.bootstrap.alert\",\"ui.bootstrap.buttons\",\"ui.bootstrap.carousel\",\"ui.bootstrap.dateparser\",\"ui.bootstrap.position\",\"ui.bootstrap.datepicker\",\"ui.bootstrap.dropdown\",\"ui.bootstrap.stackedMap\",\"ui.bootstrap.modal\",\"ui.bootstrap.pagination\",\"ui.bootstrap.tooltip\",\"ui.bootstrap.popover\",\"ui.bootstrap.progressbar\",\"ui.bootstrap.rating\",\"ui.bootstrap.tabs\",\"ui.bootstrap.timepicker\",\"ui.bootstrap.typeahead\"]);\nangular.module(\"ui.bootstrap.tpls\", [\"template/accordion/accordion-group.html\",\"template/accordion/accordion.html\",\"template/alert/alert.html\",\"template/carousel/carousel.html\",\"template/carousel/slide.html\",\"template/datepicker/datepicker.html\",\"template/datepicker/day.html\",\"template/datepicker/month.html\",\"template/datepicker/popup.html\",\"template/datepicker/year.html\",\"template/modal/backdrop.html\",\"template/modal/window.html\",\"template/pagination/pager.html\",\"template/pagination/pagination.html\",\"template/tooltip/tooltip-html-popup.html\",\"template/tooltip/tooltip-popup.html\",\"template/tooltip/tooltip-template-popup.html\",\"template/popover/popover-html.html\",\"template/popover/popover-template.html\",\"template/popover/popover.html\",\"template/progressbar/bar.html\",\"template/progressbar/progress.html\",\"template/progressbar/progressbar.html\",\"template/rating/rating.html\",\"template/tabs/tab.html\",\"template/tabs/tabset.html\",\"template/timepicker/timepicker.html\",\"template/typeahead/typeahead-match.html\",\"template/typeahead/typeahead-popup.html\"]);\nangular.module('ui.bootstrap.collapse', [])\n\n .directive('uibCollapse', ['$animate', '$injector', function($animate, $injector) {\n var $animateCss = $injector.has('$animateCss') ? $injector.get('$animateCss') : null;\n return {\n link: function(scope, element, attrs) {\n function expand() {\n element.removeClass('collapse')\n .addClass('collapsing')\n .attr('aria-expanded', true)\n .attr('aria-hidden', false);\n\n if ($animateCss) {\n $animateCss(element, {\n addClass: 'in',\n easing: 'ease',\n to: { height: element[0].scrollHeight + 'px' }\n }).start().finally(expandDone);\n } else {\n $animate.addClass(element, 'in', {\n to: { height: element[0].scrollHeight + 'px' }\n }).then(expandDone);\n }\n }\n\n function expandDone() {\n element.removeClass('collapsing')\n .addClass('collapse')\n .css({height: 'auto'});\n }\n\n function collapse() {\n if (!element.hasClass('collapse') && !element.hasClass('in')) {\n return collapseDone();\n }\n\n element\n // IMPORTANT: The height must be set before adding \"collapsing\" class.\n // Otherwise, the browser attempts to animate from height 0 (in\n // collapsing class) to the given height here.\n .css({height: element[0].scrollHeight + 'px'})\n // initially all panel collapse have the collapse class, this removal\n // prevents the animation from jumping to collapsed state\n .removeClass('collapse')\n .addClass('collapsing')\n .attr('aria-expanded', false)\n .attr('aria-hidden', true);\n\n if ($animateCss) {\n $animateCss(element, {\n removeClass: 'in',\n to: {height: '0'}\n }).start().finally(collapseDone);\n } else {\n $animate.removeClass(element, 'in', {\n to: {height: '0'}\n }).then(collapseDone);\n }\n }\n\n function collapseDone() {\n element.css({height: '0'}); // Required so that collapse works when animation is disabled\n element.removeClass('collapsing')\n .addClass('collapse');\n }\n\n scope.$watch(attrs.uibCollapse, function(shouldCollapse) {\n if (shouldCollapse) {\n collapse();\n } else {\n expand();\n }\n });\n }\n };\n }]);\n\n/* Deprecated collapse below */\n\nangular.module('ui.bootstrap.collapse')\n\n .value('$collapseSuppressWarning', false)\n\n .directive('collapse', ['$animate', '$injector', '$log', '$collapseSuppressWarning', function($animate, $injector, $log, $collapseSuppressWarning) {\n var $animateCss = $injector.has('$animateCss') ? $injector.get('$animateCss') : null;\n return {\n link: function(scope, element, attrs) {\n if (!$collapseSuppressWarning) {\n $log.warn('collapse is now deprecated. Use uib-collapse instead.');\n }\n\n function expand() {\n element.removeClass('collapse')\n .addClass('collapsing')\n .attr('aria-expanded', true)\n .attr('aria-hidden', false);\n\n if ($animateCss) {\n $animateCss(element, {\n easing: 'ease',\n to: { height: element[0].scrollHeight + 'px' }\n }).start().done(expandDone);\n } else {\n $animate.animate(element, {}, {\n height: element[0].scrollHeight + 'px'\n }).then(expandDone);\n }\n }\n\n function expandDone() {\n element.removeClass('collapsing')\n .addClass('collapse in')\n .css({height: 'auto'});\n }\n\n function collapse() {\n if (!element.hasClass('collapse') && !element.hasClass('in')) {\n return collapseDone();\n }\n\n element\n // IMPORTANT: The height must be set before adding \"collapsing\" class.\n // Otherwise, the browser attempts to animate from height 0 (in\n // collapsing class) to the given height here.\n .css({height: element[0].scrollHeight + 'px'})\n // initially all panel collapse have the collapse class, this removal\n // prevents the animation from jumping to collapsed state\n .removeClass('collapse in')\n .addClass('collapsing')\n .attr('aria-expanded', false)\n .attr('aria-hidden', true);\n\n if ($animateCss) {\n $animateCss(element, {\n to: {height: '0'}\n }).start().done(collapseDone);\n } else {\n $animate.animate(element, {}, {\n height: '0'\n }).then(collapseDone);\n }\n }\n\n function collapseDone() {\n element.css({height: '0'}); // Required so that collapse works when animation is disabled\n element.removeClass('collapsing')\n .addClass('collapse');\n }\n\n scope.$watch(attrs.collapse, function(shouldCollapse) {\n if (shouldCollapse) {\n collapse();\n } else {\n expand();\n }\n });\n }\n };\n }]);\n\nangular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])\n\n.constant('uibAccordionConfig', {\n closeOthers: true\n})\n\n.controller('UibAccordionController', ['$scope', '$attrs', 'uibAccordionConfig', function($scope, $attrs, accordionConfig) {\n // This array keeps track of the accordion groups\n this.groups = [];\n\n // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to\n this.closeOthers = function(openGroup) {\n var closeOthers = angular.isDefined($attrs.closeOthers) ?\n $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;\n if (closeOthers) {\n angular.forEach(this.groups, function(group) {\n if (group !== openGroup) {\n group.isOpen = false;\n }\n });\n }\n };\n\n // This is called from the accordion-group directive to add itself to the accordion\n this.addGroup = function(groupScope) {\n var that = this;\n this.groups.push(groupScope);\n\n groupScope.$on('$destroy', function(event) {\n that.removeGroup(groupScope);\n });\n };\n\n // This is called from the accordion-group directive when to remove itself\n this.removeGroup = function(group) {\n var index = this.groups.indexOf(group);\n if (index !== -1) {\n this.groups.splice(index, 1);\n }\n };\n\n}])\n\n// The accordion directive simply sets up the directive controller\n// and adds an accordion CSS class to itself element.\n.directive('uibAccordion', function() {\n return {\n controller: 'UibAccordionController',\n controllerAs: 'accordion',\n transclude: true,\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/accordion/accordion.html';\n }\n };\n})\n\n// The accordion-group directive indicates a block of html that will expand and collapse in an accordion\n.directive('uibAccordionGroup', function() {\n return {\n require: '^uibAccordion', // We need this directive to be inside an accordion\n transclude: true, // It transcludes the contents of the directive into the template\n replace: true, // The element containing the directive will be replaced with the template\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/accordion/accordion-group.html';\n },\n scope: {\n heading: '@', // Interpolate the heading attribute onto this scope\n isOpen: '=?',\n isDisabled: '=?'\n },\n controller: function() {\n this.setHeading = function(element) {\n this.heading = element;\n };\n },\n link: function(scope, element, attrs, accordionCtrl) {\n accordionCtrl.addGroup(scope);\n\n scope.openClass = attrs.openClass || 'panel-open';\n scope.panelClass = attrs.panelClass;\n scope.$watch('isOpen', function(value) {\n element.toggleClass(scope.openClass, !!value);\n if (value) {\n accordionCtrl.closeOthers(scope);\n }\n });\n\n scope.toggleOpen = function($event) {\n if (!scope.isDisabled) {\n if (!$event || $event.which === 32) {\n scope.isOpen = !scope.isOpen;\n }\n }\n };\n }\n };\n})\n\n// Use accordion-heading below an accordion-group to provide a heading containing HTML\n.directive('uibAccordionHeading', function() {\n return {\n transclude: true, // Grab the contents to be used as the heading\n template: '', // In effect remove this element!\n replace: true,\n require: '^uibAccordionGroup',\n link: function(scope, element, attrs, accordionGroupCtrl, transclude) {\n // Pass the heading to the accordion-group controller\n // so that it can be transcluded into the right place in the template\n // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]\n accordionGroupCtrl.setHeading(transclude(scope, angular.noop));\n }\n };\n})\n\n// Use in the accordion-group template to indicate where you want the heading to be transcluded\n// You must provide the property on the accordion-group controller that will hold the transcluded element\n.directive('uibAccordionTransclude', function() {\n return {\n require: ['?^uibAccordionGroup', '?^accordionGroup'],\n link: function(scope, element, attrs, controller) {\n controller = controller[0] ? controller[0] : controller[1]; // Delete after we remove deprecation\n scope.$watch(function() { return controller[attrs.uibAccordionTransclude]; }, function(heading) {\n if (heading) {\n element.find('span').html('');\n element.find('span').append(heading);\n }\n });\n }\n };\n});\n\n/* Deprecated accordion below */\n\nangular.module('ui.bootstrap.accordion')\n\n .value('$accordionSuppressWarning', false)\n\n .controller('AccordionController', ['$scope', '$attrs', '$controller', '$log', '$accordionSuppressWarning', function($scope, $attrs, $controller, $log, $accordionSuppressWarning) {\n if (!$accordionSuppressWarning) {\n $log.warn('AccordionController is now deprecated. Use UibAccordionController instead.');\n }\n\n angular.extend(this, $controller('UibAccordionController', {\n $scope: $scope,\n $attrs: $attrs\n }));\n }])\n\n .directive('accordion', ['$log', '$accordionSuppressWarning', function($log, $accordionSuppressWarning) {\n return {\n restrict: 'EA',\n controller: 'AccordionController',\n controllerAs: 'accordion',\n transclude: true,\n replace: false,\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/accordion/accordion.html';\n },\n link: function() {\n if (!$accordionSuppressWarning) {\n $log.warn('accordion is now deprecated. Use uib-accordion instead.');\n }\n }\n };\n }])\n\n .directive('accordionGroup', ['$log', '$accordionSuppressWarning', function($log, $accordionSuppressWarning) {\n return {\n require: '^accordion', // We need this directive to be inside an accordion\n restrict: 'EA',\n transclude: true, // It transcludes the contents of the directive into the template\n replace: true, // The element containing the directive will be replaced with the template\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/accordion/accordion-group.html';\n },\n scope: {\n heading: '@', // Interpolate the heading attribute onto this scope\n isOpen: '=?',\n isDisabled: '=?'\n },\n controller: function() {\n this.setHeading = function(element) {\n this.heading = element;\n };\n },\n link: function(scope, element, attrs, accordionCtrl) {\n if (!$accordionSuppressWarning) {\n $log.warn('accordion-group is now deprecated. Use uib-accordion-group instead.');\n }\n\n accordionCtrl.addGroup(scope);\n\n scope.openClass = attrs.openClass || 'panel-open';\n scope.panelClass = attrs.panelClass;\n scope.$watch('isOpen', function(value) {\n element.toggleClass(scope.openClass, !!value);\n if (value) {\n accordionCtrl.closeOthers(scope);\n }\n });\n\n scope.toggleOpen = function($event) {\n if (!scope.isDisabled) {\n if (!$event || $event.which === 32) {\n scope.isOpen = !scope.isOpen;\n }\n }\n };\n }\n };\n }])\n\n .directive('accordionHeading', ['$log', '$accordionSuppressWarning', function($log, $accordionSuppressWarning) {\n return {\n restrict: 'EA',\n transclude: true, // Grab the contents to be used as the heading\n template: '', // In effect remove this element!\n replace: true,\n require: '^accordionGroup',\n link: function(scope, element, attr, accordionGroupCtrl, transclude) {\n if (!$accordionSuppressWarning) {\n $log.warn('accordion-heading is now deprecated. Use uib-accordion-heading instead.');\n }\n // Pass the heading to the accordion-group controller\n // so that it can be transcluded into the right place in the template\n // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]\n accordionGroupCtrl.setHeading(transclude(scope, angular.noop));\n }\n };\n }])\n\n .directive('accordionTransclude', ['$log', '$accordionSuppressWarning', function($log, $accordionSuppressWarning) {\n return {\n require: '^accordionGroup',\n link: function(scope, element, attr, controller) {\n if (!$accordionSuppressWarning) {\n $log.warn('accordion-transclude is now deprecated. Use uib-accordion-transclude instead.');\n }\n\n scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) {\n if (heading) {\n element.find('span').html('');\n element.find('span').append(heading);\n }\n });\n }\n };\n }]);\n\n\nangular.module('ui.bootstrap.alert', [])\n\n.controller('UibAlertController', ['$scope', '$attrs', '$interpolate', '$timeout', function($scope, $attrs, $interpolate, $timeout) {\n $scope.closeable = !!$attrs.close;\n\n var dismissOnTimeout = angular.isDefined($attrs.dismissOnTimeout) ?\n $interpolate($attrs.dismissOnTimeout)($scope.$parent) : null;\n\n if (dismissOnTimeout) {\n $timeout(function() {\n $scope.close();\n }, parseInt(dismissOnTimeout, 10));\n }\n}])\n\n.directive('uibAlert', function() {\n return {\n controller: 'UibAlertController',\n controllerAs: 'alert',\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/alert/alert.html';\n },\n transclude: true,\n replace: true,\n scope: {\n type: '@',\n close: '&'\n }\n };\n});\n\n/* Deprecated alert below */\n\nangular.module('ui.bootstrap.alert')\n\n .value('$alertSuppressWarning', false)\n\n .controller('AlertController', ['$scope', '$attrs', '$controller', '$log', '$alertSuppressWarning', function($scope, $attrs, $controller, $log, $alertSuppressWarning) {\n if (!$alertSuppressWarning) {\n $log.warn('AlertController is now deprecated. Use UibAlertController instead.');\n }\n\n angular.extend(this, $controller('UibAlertController', {\n $scope: $scope,\n $attrs: $attrs\n }));\n }])\n\n .directive('alert', ['$log', '$alertSuppressWarning', function($log, $alertSuppressWarning) {\n return {\n controller: 'AlertController',\n controllerAs: 'alert',\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/alert/alert.html';\n },\n transclude: true,\n replace: true,\n scope: {\n type: '@',\n close: '&'\n },\n link: function() {\n if (!$alertSuppressWarning) {\n $log.warn('alert is now deprecated. Use uib-alert instead.');\n }\n }\n };\n }]);\n\nangular.module('ui.bootstrap.buttons', [])\n\n.constant('uibButtonConfig', {\n activeClass: 'active',\n toggleEvent: 'click'\n})\n\n.controller('UibButtonsController', ['uibButtonConfig', function(buttonConfig) {\n this.activeClass = buttonConfig.activeClass || 'active';\n this.toggleEvent = buttonConfig.toggleEvent || 'click';\n}])\n\n.directive('uibBtnRadio', function() {\n return {\n require: ['uibBtnRadio', 'ngModel'],\n controller: 'UibButtonsController',\n controllerAs: 'buttons',\n link: function(scope, element, attrs, ctrls) {\n var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n element.find('input').css({display: 'none'});\n\n //model -> UI\n ngModelCtrl.$render = function() {\n element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.uibBtnRadio)));\n };\n\n //ui->model\n element.on(buttonsCtrl.toggleEvent, function() {\n if (attrs.disabled) {\n return;\n }\n\n var isActive = element.hasClass(buttonsCtrl.activeClass);\n\n if (!isActive || angular.isDefined(attrs.uncheckable)) {\n scope.$apply(function() {\n ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.uibBtnRadio));\n ngModelCtrl.$render();\n });\n }\n });\n }\n };\n})\n\n.directive('uibBtnCheckbox', function() {\n return {\n require: ['uibBtnCheckbox', 'ngModel'],\n controller: 'UibButtonsController',\n controllerAs: 'button',\n link: function(scope, element, attrs, ctrls) {\n var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n element.find('input').css({display: 'none'});\n\n function getTrueValue() {\n return getCheckboxValue(attrs.btnCheckboxTrue, true);\n }\n\n function getFalseValue() {\n return getCheckboxValue(attrs.btnCheckboxFalse, false);\n }\n\n function getCheckboxValue(attribute, defaultValue) {\n return angular.isDefined(attribute) ? scope.$eval(attribute) : defaultValue;\n }\n\n //model -> UI\n ngModelCtrl.$render = function() {\n element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));\n };\n\n //ui->model\n element.on(buttonsCtrl.toggleEvent, function() {\n if (attrs.disabled) {\n return;\n }\n\n scope.$apply(function() {\n ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());\n ngModelCtrl.$render();\n });\n });\n }\n };\n});\n\n/* Deprecated buttons below */\n\nangular.module('ui.bootstrap.buttons')\n\n .value('$buttonsSuppressWarning', false)\n\n .controller('ButtonsController', ['$controller', '$log', '$buttonsSuppressWarning', function($controller, $log, $buttonsSuppressWarning) {\n if (!$buttonsSuppressWarning) {\n $log.warn('ButtonsController is now deprecated. Use UibButtonsController instead.');\n }\n\n angular.extend(this, $controller('UibButtonsController'));\n }])\n\n .directive('btnRadio', ['$log', '$buttonsSuppressWarning', function($log, $buttonsSuppressWarning) {\n return {\n require: ['btnRadio', 'ngModel'],\n controller: 'ButtonsController',\n controllerAs: 'buttons',\n link: function(scope, element, attrs, ctrls) {\n if (!$buttonsSuppressWarning) {\n $log.warn('btn-radio is now deprecated. Use uib-btn-radio instead.');\n }\n\n var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n element.find('input').css({display: 'none'});\n\n //model -> UI\n ngModelCtrl.$render = function() {\n element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio)));\n };\n\n //ui->model\n element.bind(buttonsCtrl.toggleEvent, function() {\n if (attrs.disabled) {\n return;\n }\n\n var isActive = element.hasClass(buttonsCtrl.activeClass);\n\n if (!isActive || angular.isDefined(attrs.uncheckable)) {\n scope.$apply(function() {\n ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio));\n ngModelCtrl.$render();\n });\n }\n });\n }\n };\n }])\n\n .directive('btnCheckbox', ['$document', '$log', '$buttonsSuppressWarning', function($document, $log, $buttonsSuppressWarning) {\n return {\n require: ['btnCheckbox', 'ngModel'],\n controller: 'ButtonsController',\n controllerAs: 'button',\n link: function(scope, element, attrs, ctrls) {\n if (!$buttonsSuppressWarning) {\n $log.warn('btn-checkbox is now deprecated. Use uib-btn-checkbox instead.');\n }\n\n var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n element.find('input').css({display: 'none'});\n\n function getTrueValue() {\n return getCheckboxValue(attrs.btnCheckboxTrue, true);\n }\n\n function getFalseValue() {\n return getCheckboxValue(attrs.btnCheckboxFalse, false);\n }\n\n function getCheckboxValue(attributeValue, defaultValue) {\n var val = scope.$eval(attributeValue);\n return angular.isDefined(val) ? val : defaultValue;\n }\n\n //model -> UI\n ngModelCtrl.$render = function() {\n element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));\n };\n\n //ui->model\n element.bind(buttonsCtrl.toggleEvent, function() {\n if (attrs.disabled) {\n return;\n }\n\n scope.$apply(function() {\n ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());\n ngModelCtrl.$render();\n });\n });\n\n //accessibility\n element.on('keypress', function(e) {\n if (attrs.disabled || e.which !== 32 || $document[0].activeElement !== element[0]) {\n return;\n }\n\n scope.$apply(function() {\n ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());\n ngModelCtrl.$render();\n });\n });\n }\n };\n }]);\n\n\n/**\n * @ngdoc overview\n * @name ui.bootstrap.carousel\n *\n * @description\n * AngularJS version of an image carousel.\n *\n */\nangular.module('ui.bootstrap.carousel', [])\n\n.controller('UibCarouselController', ['$scope', '$element', '$interval', '$animate', function($scope, $element, $interval, $animate) {\n var self = this,\n slides = self.slides = $scope.slides = [],\n NEW_ANIMATE = angular.version.minor >= 4,\n NO_TRANSITION = 'uib-noTransition',\n SLIDE_DIRECTION = 'uib-slideDirection',\n currentIndex = -1,\n currentInterval, isPlaying;\n self.currentSlide = null;\n\n var destroyed = false;\n /* direction: \"prev\" or \"next\" */\n self.select = $scope.select = function(nextSlide, direction) {\n var nextIndex = $scope.indexOfSlide(nextSlide);\n //Decide direction if it's not given\n if (direction === undefined) {\n direction = nextIndex > self.getCurrentIndex() ? 'next' : 'prev';\n }\n //Prevent this user-triggered transition from occurring if there is already one in progress\n if (nextSlide && nextSlide !== self.currentSlide && !$scope.$currentTransition) {\n goNext(nextSlide, nextIndex, direction);\n }\n };\n\n function goNext(slide, index, direction) {\n // Scope has been destroyed, stop here.\n if (destroyed) { return; }\n\n angular.extend(slide, {direction: direction, active: true});\n angular.extend(self.currentSlide || {}, {direction: direction, active: false});\n if ($animate.enabled() && !$scope.noTransition && !$scope.$currentTransition &&\n slide.$element && self.slides.length > 1) {\n slide.$element.data(SLIDE_DIRECTION, slide.direction);\n if (self.currentSlide && self.currentSlide.$element) {\n self.currentSlide.$element.data(SLIDE_DIRECTION, slide.direction);\n }\n\n $scope.$currentTransition = true;\n if (NEW_ANIMATE) {\n $animate.on('addClass', slide.$element, function(element, phase) {\n if (phase === 'close') {\n $scope.$currentTransition = null;\n $animate.off('addClass', element);\n }\n });\n } else {\n slide.$element.one('$animate:close', function closeFn() {\n $scope.$currentTransition = null;\n });\n }\n }\n\n self.currentSlide = slide;\n currentIndex = index;\n\n //every time you change slides, reset the timer\n restartTimer();\n }\n\n $scope.$on('$destroy', function() {\n destroyed = true;\n });\n\n function getSlideByIndex(index) {\n if (angular.isUndefined(slides[index].index)) {\n return slides[index];\n }\n var i, len = slides.length;\n for (i = 0; i < slides.length; ++i) {\n if (slides[i].index == index) {\n return slides[i];\n }\n }\n }\n\n self.getCurrentIndex = function() {\n if (self.currentSlide && angular.isDefined(self.currentSlide.index)) {\n return +self.currentSlide.index;\n }\n return currentIndex;\n };\n\n /* Allow outside people to call indexOf on slides array */\n $scope.indexOfSlide = function(slide) {\n return angular.isDefined(slide.index) ? +slide.index : slides.indexOf(slide);\n };\n\n $scope.next = function() {\n var newIndex = (self.getCurrentIndex() + 1) % slides.length;\n\n if (newIndex === 0 && $scope.noWrap()) {\n $scope.pause();\n return;\n }\n\n return self.select(getSlideByIndex(newIndex), 'next');\n };\n\n $scope.prev = function() {\n var newIndex = self.getCurrentIndex() - 1 < 0 ? slides.length - 1 : self.getCurrentIndex() - 1;\n\n if ($scope.noWrap() && newIndex === slides.length - 1) {\n $scope.pause();\n return;\n }\n\n return self.select(getSlideByIndex(newIndex), 'prev');\n };\n\n $scope.isActive = function(slide) {\n return self.currentSlide === slide;\n };\n\n $scope.$watch('interval', restartTimer);\n $scope.$watchCollection('slides', resetTransition);\n $scope.$on('$destroy', resetTimer);\n\n function restartTimer() {\n resetTimer();\n var interval = +$scope.interval;\n if (!isNaN(interval) && interval > 0) {\n currentInterval = $interval(timerFn, interval);\n }\n }\n\n function resetTimer() {\n if (currentInterval) {\n $interval.cancel(currentInterval);\n currentInterval = null;\n }\n }\n\n function timerFn() {\n var interval = +$scope.interval;\n if (isPlaying && !isNaN(interval) && interval > 0 && slides.length) {\n $scope.next();\n } else {\n $scope.pause();\n }\n }\n\n function resetTransition(slides) {\n if (!slides.length) {\n $scope.$currentTransition = null;\n }\n }\n\n $scope.play = function() {\n if (!isPlaying) {\n isPlaying = true;\n restartTimer();\n }\n };\n $scope.pause = function() {\n if (!$scope.noPause) {\n isPlaying = false;\n resetTimer();\n }\n };\n\n self.addSlide = function(slide, element) {\n slide.$element = element;\n slides.push(slide);\n //if this is the first slide or the slide is set to active, select it\n if (slides.length === 1 || slide.active) {\n self.select(slides[slides.length - 1]);\n if (slides.length === 1) {\n $scope.play();\n }\n } else {\n slide.active = false;\n }\n };\n\n self.removeSlide = function(slide) {\n if (angular.isDefined(slide.index)) {\n slides.sort(function(a, b) {\n return +a.index > +b.index;\n });\n }\n //get the index of the slide inside the carousel\n var index = slides.indexOf(slide);\n slides.splice(index, 1);\n if (slides.length > 0 && slide.active) {\n if (index >= slides.length) {\n self.select(slides[index - 1]);\n } else {\n self.select(slides[index]);\n }\n } else if (currentIndex > index) {\n currentIndex--;\n }\n\n //clean the currentSlide when no more slide\n if (slides.length === 0) {\n self.currentSlide = null;\n }\n };\n\n $scope.$watch('noTransition', function(noTransition) {\n $element.data(NO_TRANSITION, noTransition);\n });\n\n}])\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.carousel.directive:carousel\n * @restrict EA\n *\n * @description\n * Carousel is the outer container for a set of image 'slides' to showcase.\n *\n * @param {number=} interval The time, in milliseconds, that it will take the carousel to go to the next slide.\n * @param {boolean=} noTransition Whether to disable transitions on the carousel.\n * @param {boolean=} noPause Whether to disable pausing on the carousel (by default, the carousel interval pauses on hover).\n *\n * @example\n\n \n \n \n
\n \n \n \n
\n \n \n \n \n \n .carousel-indicators {\n top: auto;\n bottom: 15px;\n }\n \n\n */\n.directive('uibCarousel', [function() {\n return {\n transclude: true,\n replace: true,\n controller: 'UibCarouselController',\n controllerAs: 'carousel',\n require: 'carousel',\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/carousel/carousel.html';\n },\n scope: {\n interval: '=',\n noTransition: '=',\n noPause: '=',\n noWrap: '&'\n }\n };\n}])\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.carousel.directive:slide\n * @restrict EA\n *\n * @description\n * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}. Must be placed as a child of a carousel element.\n *\n * @param {boolean=} active Model binding, whether or not this slide is currently active.\n * @param {number=} index The index of the slide. The slides will be sorted by this parameter.\n *\n * @example\n\n \n\n
\n \n
\n \n
Slide {{$index}}
\n
{{slide.text}}
\n
\n \n \n Interval, in milliseconds:
\n
Enter a negative number to stop the interval.\n
\n \n \nfunction CarouselDemoCtrl($scope) {\n $scope.myInterval = 5000;\n}\n \n \n .carousel-indicators {\n top: auto;\n bottom: 15px;\n }\n \n\n*/\n\n.directive('uibSlide', function() {\n return {\n require: '^uibCarousel',\n restrict: 'EA',\n transclude: true,\n replace: true,\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/carousel/slide.html';\n },\n scope: {\n active: '=?',\n actual: '=?',\n index: '=?'\n },\n link: function (scope, element, attrs, carouselCtrl) {\n carouselCtrl.addSlide(scope, element);\n //when the scope is destroyed then remove the slide from the current slides array\n scope.$on('$destroy', function() {\n carouselCtrl.removeSlide(scope);\n });\n\n scope.$watch('active', function(active) {\n if (active) {\n carouselCtrl.select(scope);\n }\n });\n }\n };\n})\n\n.animation('.item', [\n '$injector', '$animate',\nfunction ($injector, $animate) {\n var NO_TRANSITION = 'uib-noTransition',\n SLIDE_DIRECTION = 'uib-slideDirection',\n $animateCss = null;\n\n if ($injector.has('$animateCss')) {\n $animateCss = $injector.get('$animateCss');\n }\n\n function removeClass(element, className, callback) {\n element.removeClass(className);\n if (callback) {\n callback();\n }\n }\n\n return {\n beforeAddClass: function(element, className, done) {\n // Due to transclusion, noTransition property is on parent's scope\n if (className == 'active' && element.parent() && element.parent().parent() &&\n !element.parent().parent().data(NO_TRANSITION)) {\n var stopped = false;\n var direction = element.data(SLIDE_DIRECTION);\n var directionClass = direction == 'next' ? 'left' : 'right';\n var removeClassFn = removeClass.bind(this, element,\n directionClass + ' ' + direction, done);\n element.addClass(direction);\n\n if ($animateCss) {\n $animateCss(element, {addClass: directionClass})\n .start()\n .done(removeClassFn);\n } else {\n $animate.addClass(element, directionClass).then(function () {\n if (!stopped) {\n removeClassFn();\n }\n done();\n });\n }\n\n return function () {\n stopped = true;\n };\n }\n done();\n },\n beforeRemoveClass: function (element, className, done) {\n // Due to transclusion, noTransition property is on parent's scope\n if (className === 'active' && element.parent() && element.parent().parent() &&\n !element.parent().parent().data(NO_TRANSITION)) {\n var stopped = false;\n var direction = element.data(SLIDE_DIRECTION);\n var directionClass = direction == 'next' ? 'left' : 'right';\n var removeClassFn = removeClass.bind(this, element, directionClass, done);\n\n if ($animateCss) {\n $animateCss(element, {addClass: directionClass})\n .start()\n .done(removeClassFn);\n } else {\n $animate.addClass(element, directionClass).then(function() {\n if (!stopped) {\n removeClassFn();\n }\n done();\n });\n }\n return function() {\n stopped = true;\n };\n }\n done();\n }\n };\n}]);\n\n/* deprecated carousel below */\n\nangular.module('ui.bootstrap.carousel')\n\n.value('$carouselSuppressWarning', false)\n\n.controller('CarouselController', ['$scope', '$element', '$controller', '$log', '$carouselSuppressWarning', function($scope, $element, $controller, $log, $carouselSuppressWarning) {\n if (!$carouselSuppressWarning) {\n $log.warn('CarouselController is now deprecated. Use UibCarouselController instead.');\n }\n\n angular.extend(this, $controller('UibCarouselController', {\n $scope: $scope,\n $element: $element\n }));\n}])\n\n.directive('carousel', ['$log', '$carouselSuppressWarning', function($log, $carouselSuppressWarning) {\n return {\n transclude: true,\n replace: true,\n controller: 'CarouselController',\n controllerAs: 'carousel',\n require: 'carousel',\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/carousel/carousel.html';\n },\n scope: {\n interval: '=',\n noTransition: '=',\n noPause: '=',\n noWrap: '&'\n },\n link: function() {\n if (!$carouselSuppressWarning) {\n $log.warn('carousel is now deprecated. Use uib-carousel instead.');\n }\n }\n };\n}])\n\n.directive('slide', ['$log', '$carouselSuppressWarning', function($log, $carouselSuppressWarning) {\n return {\n require: '^carousel',\n transclude: true,\n replace: true,\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/carousel/slide.html';\n },\n scope: {\n active: '=?',\n actual: '=?',\n index: '=?'\n },\n link: function (scope, element, attrs, carouselCtrl) {\n if (!$carouselSuppressWarning) {\n $log.warn('slide is now deprecated. Use uib-slide instead.');\n }\n\n carouselCtrl.addSlide(scope, element);\n //when the scope is destroyed then remove the slide from the current slides array\n scope.$on('$destroy', function() {\n carouselCtrl.removeSlide(scope);\n });\n\n scope.$watch('active', function(active) {\n if (active) {\n carouselCtrl.select(scope);\n }\n });\n }\n };\n}]);\n\nangular.module('ui.bootstrap.dateparser', [])\n\n.service('uibDateParser', ['$log', '$locale', 'orderByFilter', function($log, $locale, orderByFilter) {\n // Pulled from https://github.com/mbostock/d3/blob/master/src/format/requote.js\n var SPECIAL_CHARACTERS_REGEXP = /[\\\\\\^\\$\\*\\+\\?\\|\\[\\]\\(\\)\\.\\{\\}]/g;\n\n var localeId;\n var formatCodeToRegex;\n\n this.init = function() {\n localeId = $locale.id;\n\n this.parsers = {};\n\n formatCodeToRegex = {\n 'yyyy': {\n regex: '\\\\d{4}',\n apply: function(value) { this.year = +value; }\n },\n 'yy': {\n regex: '\\\\d{2}',\n apply: function(value) { this.year = +value + 2000; }\n },\n 'y': {\n regex: '\\\\d{1,4}',\n apply: function(value) { this.year = +value; }\n },\n 'MMMM': {\n regex: $locale.DATETIME_FORMATS.MONTH.join('|'),\n apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); }\n },\n 'MMM': {\n regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),\n apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); }\n },\n 'MM': {\n regex: '0[1-9]|1[0-2]',\n apply: function(value) { this.month = value - 1; }\n },\n 'M': {\n regex: '[1-9]|1[0-2]',\n apply: function(value) { this.month = value - 1; }\n },\n 'dd': {\n regex: '[0-2][0-9]{1}|3[0-1]{1}',\n apply: function(value) { this.date = +value; }\n },\n 'd': {\n regex: '[1-2]?[0-9]{1}|3[0-1]{1}',\n apply: function(value) { this.date = +value; }\n },\n 'EEEE': {\n regex: $locale.DATETIME_FORMATS.DAY.join('|')\n },\n 'EEE': {\n regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|')\n },\n 'HH': {\n regex: '(?:0|1)[0-9]|2[0-3]',\n apply: function(value) { this.hours = +value; }\n },\n 'hh': {\n regex: '0[0-9]|1[0-2]',\n apply: function(value) { this.hours = +value; }\n },\n 'H': {\n regex: '1?[0-9]|2[0-3]',\n apply: function(value) { this.hours = +value; }\n },\n 'h': {\n regex: '[0-9]|1[0-2]',\n apply: function(value) { this.hours = +value; }\n },\n 'mm': {\n regex: '[0-5][0-9]',\n apply: function(value) { this.minutes = +value; }\n },\n 'm': {\n regex: '[0-9]|[1-5][0-9]',\n apply: function(value) { this.minutes = +value; }\n },\n 'sss': {\n regex: '[0-9][0-9][0-9]',\n apply: function(value) { this.milliseconds = +value; }\n },\n 'ss': {\n regex: '[0-5][0-9]',\n apply: function(value) { this.seconds = +value; }\n },\n 's': {\n regex: '[0-9]|[1-5][0-9]',\n apply: function(value) { this.seconds = +value; }\n },\n 'a': {\n regex: $locale.DATETIME_FORMATS.AMPMS.join('|'),\n apply: function(value) {\n if (this.hours === 12) {\n this.hours = 0;\n }\n\n if (value === 'PM') {\n this.hours += 12;\n }\n }\n }\n };\n };\n\n this.init();\n\n function createParser(format) {\n var map = [], regex = format.split('');\n\n angular.forEach(formatCodeToRegex, function(data, code) {\n var index = format.indexOf(code);\n\n if (index > -1) {\n format = format.split('');\n\n regex[index] = '(' + data.regex + ')';\n format[index] = '$'; // Custom symbol to define consumed part of format\n for (var i = index + 1, n = index + code.length; i < n; i++) {\n regex[i] = '';\n format[i] = '$';\n }\n format = format.join('');\n\n map.push({ index: index, apply: data.apply });\n }\n });\n\n return {\n regex: new RegExp('^' + regex.join('') + '$'),\n map: orderByFilter(map, 'index')\n };\n }\n\n this.parse = function(input, format, baseDate) {\n if (!angular.isString(input) || !format) {\n return input;\n }\n\n format = $locale.DATETIME_FORMATS[format] || format;\n format = format.replace(SPECIAL_CHARACTERS_REGEXP, '\\\\$&');\n\n if ($locale.id !== localeId) {\n this.init();\n }\n\n if (!this.parsers[format]) {\n this.parsers[format] = createParser(format);\n }\n\n var parser = this.parsers[format],\n regex = parser.regex,\n map = parser.map,\n results = input.match(regex);\n\n if (results && results.length) {\n var fields, dt;\n if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) {\n fields = {\n year: baseDate.getFullYear(),\n month: baseDate.getMonth(),\n date: baseDate.getDate(),\n hours: baseDate.getHours(),\n minutes: baseDate.getMinutes(),\n seconds: baseDate.getSeconds(),\n milliseconds: baseDate.getMilliseconds()\n };\n } else {\n if (baseDate) {\n $log.warn('dateparser:', 'baseDate is not a valid date');\n }\n fields = { year: 1900, month: 0, date: 1, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 };\n }\n\n for (var i = 1, n = results.length; i < n; i++) {\n var mapper = map[i-1];\n if (mapper.apply) {\n mapper.apply.call(fields, results[i]);\n }\n }\n\n if (isValid(fields.year, fields.month, fields.date)) {\n if (angular.isDate(baseDate) && !isNaN(baseDate.getTime())) {\n dt = new Date(baseDate);\n dt.setFullYear(fields.year, fields.month, fields.date,\n fields.hours, fields.minutes, fields.seconds,\n fields.milliseconds || 0);\n } else {\n dt = new Date(fields.year, fields.month, fields.date,\n fields.hours, fields.minutes, fields.seconds,\n fields.milliseconds || 0);\n }\n }\n\n return dt;\n }\n };\n\n // Check if date is valid for specific month (and year for February).\n // Month: 0 = Jan, 1 = Feb, etc\n function isValid(year, month, date) {\n if (date < 1) {\n return false;\n }\n\n if (month === 1 && date > 28) {\n return date === 29 && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);\n }\n\n if (month === 3 || month === 5 || month === 8 || month === 10) {\n return date < 31;\n }\n\n return true;\n }\n}]);\n\n/* Deprecated dateparser below */\n\nangular.module('ui.bootstrap.dateparser')\n\n.value('$dateParserSuppressWarning', false)\n\n.service('dateParser', ['$log', '$dateParserSuppressWarning', 'uibDateParser', function($log, $dateParserSuppressWarning, uibDateParser) {\n if (!$dateParserSuppressWarning) {\n $log.warn('dateParser is now deprecated. Use uibDateParser instead.');\n }\n\n angular.extend(this, uibDateParser);\n}]);\n\nangular.module('ui.bootstrap.position', [])\n\n/**\n * A set of utility methods that can be use to retrieve position of DOM elements.\n * It is meant to be used where we need to absolute-position DOM elements in\n * relation to other, existing elements (this is the case for tooltips, popovers,\n * typeahead suggestions etc.).\n */\n .factory('$uibPosition', ['$document', '$window', function($document, $window) {\n function getStyle(el, cssprop) {\n if (el.currentStyle) { //IE\n return el.currentStyle[cssprop];\n } else if ($window.getComputedStyle) {\n return $window.getComputedStyle(el)[cssprop];\n }\n // finally try and get inline style\n return el.style[cssprop];\n }\n\n /**\n * Checks if a given element is statically positioned\n * @param element - raw DOM element\n */\n function isStaticPositioned(element) {\n return (getStyle(element, 'position') || 'static' ) === 'static';\n }\n\n /**\n * returns the closest, non-statically positioned parentOffset of a given element\n * @param element\n */\n var parentOffsetEl = function(element) {\n var docDomEl = $document[0];\n var offsetParent = element.offsetParent || docDomEl;\n while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) {\n offsetParent = offsetParent.offsetParent;\n }\n return offsetParent || docDomEl;\n };\n\n return {\n /**\n * Provides read-only equivalent of jQuery's position function:\n * http://api.jquery.com/position/\n */\n position: function(element) {\n var elBCR = this.offset(element);\n var offsetParentBCR = { top: 0, left: 0 };\n var offsetParentEl = parentOffsetEl(element[0]);\n if (offsetParentEl != $document[0]) {\n offsetParentBCR = this.offset(angular.element(offsetParentEl));\n offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;\n offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;\n }\n\n var boundingClientRect = element[0].getBoundingClientRect();\n return {\n width: boundingClientRect.width || element.prop('offsetWidth'),\n height: boundingClientRect.height || element.prop('offsetHeight'),\n top: elBCR.top - offsetParentBCR.top,\n left: elBCR.left - offsetParentBCR.left\n };\n },\n\n /**\n * Provides read-only equivalent of jQuery's offset function:\n * http://api.jquery.com/offset/\n */\n offset: function(element) {\n var boundingClientRect = element[0].getBoundingClientRect();\n return {\n width: boundingClientRect.width || element.prop('offsetWidth'),\n height: boundingClientRect.height || element.prop('offsetHeight'),\n top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop),\n left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft)\n };\n },\n\n /**\n * Provides coordinates for the targetEl in relation to hostEl\n */\n positionElements: function(hostEl, targetEl, positionStr, appendToBody) {\n var positionStrParts = positionStr.split('-');\n var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center';\n\n var hostElPos,\n targetElWidth,\n targetElHeight,\n targetElPos;\n\n hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl);\n\n targetElWidth = targetEl.prop('offsetWidth');\n targetElHeight = targetEl.prop('offsetHeight');\n\n var shiftWidth = {\n center: function() {\n return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2;\n },\n left: function() {\n return hostElPos.left;\n },\n right: function() {\n return hostElPos.left + hostElPos.width;\n }\n };\n\n var shiftHeight = {\n center: function() {\n return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2;\n },\n top: function() {\n return hostElPos.top;\n },\n bottom: function() {\n return hostElPos.top + hostElPos.height;\n }\n };\n\n switch (pos0) {\n case 'right':\n targetElPos = {\n top: shiftHeight[pos1](),\n left: shiftWidth[pos0]()\n };\n break;\n case 'left':\n targetElPos = {\n top: shiftHeight[pos1](),\n left: hostElPos.left - targetElWidth\n };\n break;\n case 'bottom':\n targetElPos = {\n top: shiftHeight[pos0](),\n left: shiftWidth[pos1]()\n };\n break;\n default:\n targetElPos = {\n top: hostElPos.top - targetElHeight,\n left: shiftWidth[pos1]()\n };\n break;\n }\n\n return targetElPos;\n }\n };\n }]);\n\n/* Deprecated position below */\n\nangular.module('ui.bootstrap.position')\n\n.value('$positionSuppressWarning', false)\n\n.service('$position', ['$log', '$positionSuppressWarning', '$uibPosition', function($log, $positionSuppressWarning, $uibPosition) {\n if (!$positionSuppressWarning) {\n $log.warn('$position is now deprecated. Use $uibPosition instead.');\n }\n\n angular.extend(this, $uibPosition);\n}]);\n\nangular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.position'])\n\n.value('$datepickerSuppressError', false)\n\n.constant('uibDatepickerConfig', {\n formatDay: 'dd',\n formatMonth: 'MMMM',\n formatYear: 'yyyy',\n formatDayHeader: 'EEE',\n formatDayTitle: 'MMMM yyyy',\n formatMonthTitle: 'yyyy',\n datepickerMode: 'day',\n minMode: 'day',\n maxMode: 'year',\n showWeeks: true,\n startingDay: 0,\n yearRange: 20,\n minDate: null,\n maxDate: null,\n shortcutPropagation: false\n})\n\n.controller('UibDatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerSuppressError', function($scope, $attrs, $parse, $interpolate, $log, dateFilter, datepickerConfig, $datepickerSuppressError) {\n var self = this,\n ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl;\n\n // Modes chain\n this.modes = ['day', 'month', 'year'];\n\n // Configuration attributes\n angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle',\n 'showWeeks', 'startingDay', 'yearRange', 'shortcutPropagation'], function(key, index) {\n self[key] = angular.isDefined($attrs[key]) ? (index < 6 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key];\n });\n\n // Watchable date attributes\n angular.forEach(['minDate', 'maxDate'], function(key) {\n if ($attrs[key]) {\n $scope.$parent.$watch($parse($attrs[key]), function(value) {\n self[key] = value ? new Date(value) : null;\n self.refreshView();\n });\n } else {\n self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null;\n }\n });\n\n angular.forEach(['minMode', 'maxMode'], function(key) {\n if ($attrs[key]) {\n $scope.$parent.$watch($parse($attrs[key]), function(value) {\n self[key] = angular.isDefined(value) ? value : $attrs[key];\n $scope[key] = self[key];\n if ((key == 'minMode' && self.modes.indexOf($scope.datepickerMode) < self.modes.indexOf(self[key])) || (key == 'maxMode' && self.modes.indexOf($scope.datepickerMode) > self.modes.indexOf(self[key]))) {\n $scope.datepickerMode = self[key];\n }\n });\n } else {\n self[key] = datepickerConfig[key] || null;\n $scope[key] = self[key];\n }\n });\n\n $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode;\n $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);\n\n if (angular.isDefined($attrs.initDate)) {\n this.activeDate = $scope.$parent.$eval($attrs.initDate) || new Date();\n $scope.$parent.$watch($attrs.initDate, function(initDate) {\n if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {\n self.activeDate = initDate;\n self.refreshView();\n }\n });\n } else {\n this.activeDate = new Date();\n }\n\n $scope.isActive = function(dateObject) {\n if (self.compare(dateObject.date, self.activeDate) === 0) {\n $scope.activeDateId = dateObject.uid;\n return true;\n }\n return false;\n };\n\n this.init = function(ngModelCtrl_) {\n ngModelCtrl = ngModelCtrl_;\n\n ngModelCtrl.$render = function() {\n self.render();\n };\n };\n\n this.render = function() {\n if (ngModelCtrl.$viewValue) {\n var date = new Date(ngModelCtrl.$viewValue),\n isValid = !isNaN(date);\n\n if (isValid) {\n this.activeDate = date;\n } else if (!$datepickerSuppressError) {\n $log.error('Datepicker directive: \"ng-model\" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');\n }\n }\n this.refreshView();\n };\n\n this.refreshView = function() {\n if (this.element) {\n this._refreshView();\n\n var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;\n ngModelCtrl.$setValidity('dateDisabled', !date || (this.element && !this.isDisabled(date)));\n }\n };\n\n this.createDateObject = function(date, format) {\n var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;\n return {\n date: date,\n label: dateFilter(date, format),\n selected: model && this.compare(date, model) === 0,\n disabled: this.isDisabled(date),\n current: this.compare(date, new Date()) === 0,\n customClass: this.customClass(date)\n };\n };\n\n this.isDisabled = function(date) {\n return ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode})));\n };\n\n this.customClass = function(date) {\n return $scope.customClass({date: date, mode: $scope.datepickerMode});\n };\n\n // Split array into smaller arrays\n this.split = function(arr, size) {\n var arrays = [];\n while (arr.length > 0) {\n arrays.push(arr.splice(0, size));\n }\n return arrays;\n };\n\n $scope.select = function(date) {\n if ($scope.datepickerMode === self.minMode) {\n var dt = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : new Date(0, 0, 0, 0, 0, 0, 0);\n dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());\n ngModelCtrl.$setViewValue(dt);\n ngModelCtrl.$render();\n } else {\n self.activeDate = date;\n $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) - 1];\n }\n };\n\n $scope.move = function(direction) {\n var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),\n month = self.activeDate.getMonth() + direction * (self.step.months || 0);\n self.activeDate.setFullYear(year, month, 1);\n self.refreshView();\n };\n\n $scope.toggleMode = function(direction) {\n direction = direction || 1;\n\n if (($scope.datepickerMode === self.maxMode && direction === 1) || ($scope.datepickerMode === self.minMode && direction === -1)) {\n return;\n }\n\n $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) + direction];\n };\n\n // Key event mapper\n $scope.keys = { 13: 'enter', 32: 'space', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home', 37: 'left', 38: 'up', 39: 'right', 40: 'down' };\n\n var focusElement = function() {\n self.element[0].focus();\n };\n\n // Listen for focus requests from popup directive\n $scope.$on('uib:datepicker.focus', focusElement);\n\n $scope.keydown = function(evt) {\n var key = $scope.keys[evt.which];\n\n if (!key || evt.shiftKey || evt.altKey) {\n return;\n }\n\n evt.preventDefault();\n if (!self.shortcutPropagation) {\n evt.stopPropagation();\n }\n\n if (key === 'enter' || key === 'space') {\n if (self.isDisabled(self.activeDate)) {\n return; // do nothing\n }\n $scope.select(self.activeDate);\n } else if (evt.ctrlKey && (key === 'up' || key === 'down')) {\n $scope.toggleMode(key === 'up' ? 1 : -1);\n } else {\n self.handleKeyDown(key, evt);\n self.refreshView();\n }\n };\n}])\n\n.controller('UibDaypickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {\n var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\n\n this.step = { months: 1 };\n this.element = $element;\n function getDaysInMonth(year, month) {\n return ((month === 1) && (year % 4 === 0) && ((year % 100 !== 0) || (year % 400 === 0))) ? 29 : DAYS_IN_MONTH[month];\n }\n\n this.init = function(ctrl) {\n angular.extend(ctrl, this);\n scope.showWeeks = ctrl.showWeeks;\n ctrl.refreshView();\n };\n\n this.getDates = function(startDate, n) {\n var dates = new Array(n), current = new Date(startDate), i = 0, date;\n while (i < n) {\n date = new Date(current);\n dates[i++] = date;\n current.setDate(current.getDate() + 1);\n }\n return dates;\n };\n\n this._refreshView = function() {\n var year = this.activeDate.getFullYear(),\n month = this.activeDate.getMonth(),\n firstDayOfMonth = new Date(this.activeDate);\n\n firstDayOfMonth.setFullYear(year, month, 1);\n\n var difference = this.startingDay - firstDayOfMonth.getDay(),\n numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference,\n firstDate = new Date(firstDayOfMonth);\n\n if (numDisplayedFromPreviousMonth > 0) {\n firstDate.setDate(-numDisplayedFromPreviousMonth + 1);\n }\n\n // 42 is the number of days on a six-month calendar\n var days = this.getDates(firstDate, 42);\n for (var i = 0; i < 42; i ++) {\n days[i] = angular.extend(this.createDateObject(days[i], this.formatDay), {\n secondary: days[i].getMonth() !== month,\n uid: scope.uniqueId + '-' + i\n });\n }\n\n scope.labels = new Array(7);\n for (var j = 0; j < 7; j++) {\n scope.labels[j] = {\n abbr: dateFilter(days[j].date, this.formatDayHeader),\n full: dateFilter(days[j].date, 'EEEE')\n };\n }\n\n scope.title = dateFilter(this.activeDate, this.formatDayTitle);\n scope.rows = this.split(days, 7);\n\n if (scope.showWeeks) {\n scope.weekNumbers = [];\n var thursdayIndex = (4 + 7 - this.startingDay) % 7,\n numWeeks = scope.rows.length;\n for (var curWeek = 0; curWeek < numWeeks; curWeek++) {\n scope.weekNumbers.push(\n getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date));\n }\n }\n };\n\n this.compare = function(date1, date2) {\n return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()));\n };\n\n function getISO8601WeekNumber(date) {\n var checkDate = new Date(date);\n checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday\n var time = checkDate.getTime();\n checkDate.setMonth(0); // Compare with Jan 1\n checkDate.setDate(1);\n return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;\n }\n\n this.handleKeyDown = function(key, evt) {\n var date = this.activeDate.getDate();\n\n if (key === 'left') {\n date = date - 1; // up\n } else if (key === 'up') {\n date = date - 7; // down\n } else if (key === 'right') {\n date = date + 1; // down\n } else if (key === 'down') {\n date = date + 7;\n } else if (key === 'pageup' || key === 'pagedown') {\n var month = this.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1);\n this.activeDate.setMonth(month, 1);\n date = Math.min(getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth()), date);\n } else if (key === 'home') {\n date = 1;\n } else if (key === 'end') {\n date = getDaysInMonth(this.activeDate.getFullYear(), this.activeDate.getMonth());\n }\n this.activeDate.setDate(date);\n };\n}])\n\n.controller('UibMonthpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {\n this.step = { years: 1 };\n this.element = $element;\n\n this.init = function(ctrl) {\n angular.extend(ctrl, this);\n ctrl.refreshView();\n };\n\n this._refreshView = function() {\n var months = new Array(12),\n year = this.activeDate.getFullYear(),\n date;\n\n for (var i = 0; i < 12; i++) {\n date = new Date(this.activeDate);\n date.setFullYear(year, i, 1);\n months[i] = angular.extend(this.createDateObject(date, this.formatMonth), {\n uid: scope.uniqueId + '-' + i\n });\n }\n\n scope.title = dateFilter(this.activeDate, this.formatMonthTitle);\n scope.rows = this.split(months, 3);\n };\n\n this.compare = function(date1, date2) {\n return new Date(date1.getFullYear(), date1.getMonth()) - new Date(date2.getFullYear(), date2.getMonth());\n };\n\n this.handleKeyDown = function(key, evt) {\n var date = this.activeDate.getMonth();\n\n if (key === 'left') {\n date = date - 1; // up\n } else if (key === 'up') {\n date = date - 3; // down\n } else if (key === 'right') {\n date = date + 1; // down\n } else if (key === 'down') {\n date = date + 3;\n } else if (key === 'pageup' || key === 'pagedown') {\n var year = this.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1);\n this.activeDate.setFullYear(year);\n } else if (key === 'home') {\n date = 0;\n } else if (key === 'end') {\n date = 11;\n }\n this.activeDate.setMonth(date);\n };\n}])\n\n.controller('UibYearpickerController', ['$scope', '$element', 'dateFilter', function(scope, $element, dateFilter) {\n var range;\n this.element = $element;\n\n function getStartingYear(year) {\n return parseInt((year - 1) / range, 10) * range + 1;\n }\n\n this.yearpickerInit = function() {\n range = this.yearRange;\n this.step = { years: range };\n };\n\n this._refreshView = function() {\n var years = new Array(range), date;\n\n for (var i = 0, start = getStartingYear(this.activeDate.getFullYear()); i < range; i++) {\n date = new Date(this.activeDate);\n date.setFullYear(start + i, 0, 1);\n years[i] = angular.extend(this.createDateObject(date, this.formatYear), {\n uid: scope.uniqueId + '-' + i\n });\n }\n\n scope.title = [years[0].label, years[range - 1].label].join(' - ');\n scope.rows = this.split(years, 5);\n };\n\n this.compare = function(date1, date2) {\n return date1.getFullYear() - date2.getFullYear();\n };\n\n this.handleKeyDown = function(key, evt) {\n var date = this.activeDate.getFullYear();\n\n if (key === 'left') {\n date = date - 1; // up\n } else if (key === 'up') {\n date = date - 5; // down\n } else if (key === 'right') {\n date = date + 1; // down\n } else if (key === 'down') {\n date = date + 5;\n } else if (key === 'pageup' || key === 'pagedown') {\n date += (key === 'pageup' ? - 1 : 1) * this.step.years;\n } else if (key === 'home') {\n date = getStartingYear(this.activeDate.getFullYear());\n } else if (key === 'end') {\n date = getStartingYear(this.activeDate.getFullYear()) + range - 1;\n }\n this.activeDate.setFullYear(date);\n };\n}])\n\n.directive('uibDatepicker', function() {\n return {\n replace: true,\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/datepicker/datepicker.html';\n },\n scope: {\n datepickerMode: '=?',\n dateDisabled: '&',\n customClass: '&',\n shortcutPropagation: '&?'\n },\n require: ['uibDatepicker', '^ngModel'],\n controller: 'UibDatepickerController',\n controllerAs: 'datepicker',\n link: function(scope, element, attrs, ctrls) {\n var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n datepickerCtrl.init(ngModelCtrl);\n }\n };\n})\n\n.directive('uibDaypicker', function() {\n return {\n replace: true,\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/datepicker/day.html';\n },\n require: ['^?uibDatepicker', 'uibDaypicker', '^?datepicker'],\n controller: 'UibDaypickerController',\n link: function(scope, element, attrs, ctrls) {\n var datepickerCtrl = ctrls[0] || ctrls[2],\n daypickerCtrl = ctrls[1];\n\n daypickerCtrl.init(datepickerCtrl);\n }\n };\n})\n\n.directive('uibMonthpicker', function() {\n return {\n replace: true,\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/datepicker/month.html';\n },\n require: ['^?uibDatepicker', 'uibMonthpicker', '^?datepicker'],\n controller: 'UibMonthpickerController',\n link: function(scope, element, attrs, ctrls) {\n var datepickerCtrl = ctrls[0] || ctrls[2],\n monthpickerCtrl = ctrls[1];\n\n monthpickerCtrl.init(datepickerCtrl);\n }\n };\n})\n\n.directive('uibYearpicker', function() {\n return {\n replace: true,\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/datepicker/year.html';\n },\n require: ['^?uibDatepicker', 'uibYearpicker', '^?datepicker'],\n controller: 'UibYearpickerController',\n link: function(scope, element, attrs, ctrls) {\n var ctrl = ctrls[0] || ctrls[2];\n angular.extend(ctrl, ctrls[1]);\n ctrl.yearpickerInit();\n\n ctrl.refreshView();\n }\n };\n})\n\n.constant('uibDatepickerPopupConfig', {\n datepickerPopup: 'yyyy-MM-dd',\n datepickerPopupTemplateUrl: 'template/datepicker/popup.html',\n datepickerTemplateUrl: 'template/datepicker/datepicker.html',\n html5Types: {\n date: 'yyyy-MM-dd',\n 'datetime-local': 'yyyy-MM-ddTHH:mm:ss.sss',\n 'month': 'yyyy-MM'\n },\n currentText: 'Today',\n clearText: 'Clear',\n closeText: 'Done',\n closeOnDateSelection: true,\n appendToBody: false,\n showButtonBar: true,\n onOpenFocus: true\n})\n\n.controller('UibDatepickerPopupController', ['$scope', '$element', '$attrs', '$compile', '$parse', '$document', '$rootScope', '$uibPosition', 'dateFilter', 'uibDateParser', 'uibDatepickerPopupConfig', '$timeout',\nfunction(scope, element, attrs, $compile, $parse, $document, $rootScope, $position, dateFilter, dateParser, datepickerPopupConfig, $timeout) {\n var self = this;\n var cache = {},\n isHtml5DateInput = false;\n var dateFormat, closeOnDateSelection, appendToBody, onOpenFocus,\n datepickerPopupTemplateUrl, datepickerTemplateUrl, popupEl, datepickerEl,\n ngModel, $popup;\n\n scope.watchData = {};\n\n this.init = function(_ngModel_) {\n ngModel = _ngModel_;\n closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection;\n appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody;\n onOpenFocus = angular.isDefined(attrs.onOpenFocus) ? scope.$parent.$eval(attrs.onOpenFocus) : datepickerPopupConfig.onOpenFocus;\n datepickerPopupTemplateUrl = angular.isDefined(attrs.datepickerPopupTemplateUrl) ? attrs.datepickerPopupTemplateUrl : datepickerPopupConfig.datepickerPopupTemplateUrl;\n datepickerTemplateUrl = angular.isDefined(attrs.datepickerTemplateUrl) ? attrs.datepickerTemplateUrl : datepickerPopupConfig.datepickerTemplateUrl;\n\n scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar;\n\n if (datepickerPopupConfig.html5Types[attrs.type]) {\n dateFormat = datepickerPopupConfig.html5Types[attrs.type];\n isHtml5DateInput = true;\n } else {\n dateFormat = attrs.datepickerPopup || attrs.uibDatepickerPopup || datepickerPopupConfig.datepickerPopup;\n attrs.$observe('uibDatepickerPopup', function(value, oldValue) {\n var newDateFormat = value || datepickerPopupConfig.datepickerPopup;\n // Invalidate the $modelValue to ensure that formatters re-run\n // FIXME: Refactor when PR is merged: https://github.com/angular/angular.js/pull/10764\n if (newDateFormat !== dateFormat) {\n dateFormat = newDateFormat;\n ngModel.$modelValue = null;\n\n if (!dateFormat) {\n throw new Error('uibDatepickerPopup must have a date format specified.');\n }\n }\n });\n }\n\n if (!dateFormat) {\n throw new Error('uibDatepickerPopup must have a date format specified.');\n }\n\n if (isHtml5DateInput && attrs.datepickerPopup) {\n throw new Error('HTML5 date input types do not support custom formats.');\n }\n\n // popup element used to display calendar\n popupEl = angular.element('');\n popupEl.attr({\n 'ng-model': 'date',\n 'ng-change': 'dateSelection(date)',\n 'template-url': datepickerPopupTemplateUrl\n });\n\n // datepicker element\n datepickerEl = angular.element(popupEl.children()[0]);\n datepickerEl.attr('template-url', datepickerTemplateUrl);\n\n if (isHtml5DateInput) {\n if (attrs.type === 'month') {\n datepickerEl.attr('datepicker-mode', '\"month\"');\n datepickerEl.attr('min-mode', 'month');\n }\n }\n\n if (attrs.datepickerOptions) {\n var options = scope.$parent.$eval(attrs.datepickerOptions);\n if (options && options.initDate) {\n scope.initDate = options.initDate;\n datepickerEl.attr('init-date', 'initDate');\n delete options.initDate;\n }\n angular.forEach(options, function(value, option) {\n datepickerEl.attr(cameltoDash(option), value);\n });\n }\n\n angular.forEach(['minMode', 'maxMode', 'minDate', 'maxDate', 'datepickerMode', 'initDate', 'shortcutPropagation'], function(key) {\n if (attrs[key]) {\n var getAttribute = $parse(attrs[key]);\n scope.$parent.$watch(getAttribute, function(value) {\n scope.watchData[key] = value;\n if (key === 'minDate' || key === 'maxDate') {\n cache[key] = new Date(value);\n }\n });\n datepickerEl.attr(cameltoDash(key), 'watchData.' + key);\n\n // Propagate changes from datepicker to outside\n if (key === 'datepickerMode') {\n var setAttribute = getAttribute.assign;\n scope.$watch('watchData.' + key, function(value, oldvalue) {\n if (angular.isFunction(setAttribute) && value !== oldvalue) {\n setAttribute(scope.$parent, value);\n }\n });\n }\n }\n });\n if (attrs.dateDisabled) {\n datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })');\n }\n\n if (attrs.showWeeks) {\n datepickerEl.attr('show-weeks', attrs.showWeeks);\n }\n\n if (attrs.customClass) {\n datepickerEl.attr('custom-class', 'customClass({ date: date, mode: mode })');\n }\n\n if (!isHtml5DateInput) {\n // Internal API to maintain the correct ng-invalid-[key] class\n ngModel.$$parserName = 'date';\n ngModel.$validators.date = validator;\n ngModel.$parsers.unshift(parseDate);\n ngModel.$formatters.push(function(value) {\n scope.date = value;\n return ngModel.$isEmpty(value) ? value : dateFilter(value, dateFormat);\n });\n } else {\n ngModel.$formatters.push(function(value) {\n scope.date = value;\n return value;\n });\n }\n\n // Detect changes in the view from the text box\n ngModel.$viewChangeListeners.push(function() {\n scope.date = dateParser.parse(ngModel.$viewValue, dateFormat, scope.date);\n });\n\n element.bind('keydown', inputKeydownBind);\n\n $popup = $compile(popupEl)(scope);\n // Prevent jQuery cache memory leak (template is now redundant after linking)\n popupEl.remove();\n\n if (appendToBody) {\n $document.find('body').append($popup);\n } else {\n element.after($popup);\n }\n\n scope.$on('$destroy', function() {\n if (scope.isOpen === true) {\n if (!$rootScope.$$phase) {\n scope.$apply(function() {\n scope.isOpen = false;\n });\n }\n }\n\n $popup.remove();\n element.unbind('keydown', inputKeydownBind);\n $document.unbind('click', documentClickBind);\n });\n };\n\n scope.getText = function(key) {\n return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];\n };\n\n scope.isDisabled = function(date) {\n if (date === 'today') {\n date = new Date();\n }\n\n return ((scope.watchData.minDate && scope.compare(date, cache.minDate) < 0) ||\n (scope.watchData.maxDate && scope.compare(date, cache.maxDate) > 0));\n };\n\n scope.compare = function(date1, date2) {\n return (new Date(date1.getFullYear(), date1.getMonth(), date1.getDate()) - new Date(date2.getFullYear(), date2.getMonth(), date2.getDate()));\n };\n\n // Inner change\n scope.dateSelection = function(dt) {\n if (angular.isDefined(dt)) {\n scope.date = dt;\n }\n var date = scope.date ? dateFilter(scope.date, dateFormat) : null; // Setting to NULL is necessary for form validators to function\n element.val(date);\n ngModel.$setViewValue(date);\n\n if (closeOnDateSelection) {\n scope.isOpen = false;\n element[0].focus();\n }\n };\n\n scope.keydown = function(evt) {\n if (evt.which === 27) {\n scope.isOpen = false;\n element[0].focus();\n }\n };\n\n scope.select = function(date) {\n if (date === 'today') {\n var today = new Date();\n if (angular.isDate(scope.date)) {\n date = new Date(scope.date);\n date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());\n } else {\n date = new Date(today.setHours(0, 0, 0, 0));\n }\n }\n scope.dateSelection(date);\n };\n\n scope.close = function() {\n scope.isOpen = false;\n element[0].focus();\n };\n\n scope.$watch('isOpen', function(value) {\n if (value) {\n scope.position = appendToBody ? $position.offset(element) : $position.position(element);\n scope.position.top = scope.position.top + element.prop('offsetHeight');\n\n $timeout(function() {\n if (onOpenFocus) {\n scope.$broadcast('uib:datepicker.focus');\n }\n $document.bind('click', documentClickBind);\n }, 0, false);\n } else {\n $document.unbind('click', documentClickBind);\n }\n });\n\n function cameltoDash(string) {\n return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); });\n }\n\n function parseDate(viewValue) {\n if (angular.isNumber(viewValue)) {\n // presumably timestamp to date object\n viewValue = new Date(viewValue);\n }\n\n if (!viewValue) {\n return null;\n } else if (angular.isDate(viewValue) && !isNaN(viewValue)) {\n return viewValue;\n } else if (angular.isString(viewValue)) {\n var date = dateParser.parse(viewValue, dateFormat, scope.date);\n if (isNaN(date)) {\n return undefined;\n } else {\n return date;\n }\n } else {\n return undefined;\n }\n }\n\n function validator(modelValue, viewValue) {\n var value = modelValue || viewValue;\n\n if (!attrs.ngRequired && !value) {\n return true;\n }\n\n if (angular.isNumber(value)) {\n value = new Date(value);\n }\n if (!value) {\n return true;\n } else if (angular.isDate(value) && !isNaN(value)) {\n return true;\n } else if (angular.isString(value)) {\n var date = dateParser.parse(value, dateFormat);\n return !isNaN(date);\n } else {\n return false;\n }\n }\n\n function documentClickBind(event) {\n var popup = $popup[0];\n var dpContainsTarget = element[0].contains(event.target);\n // The popup node may not be an element node\n // In some browsers (IE) only element nodes have the 'contains' function\n var popupContainsTarget = popup.contains !== undefined && popup.contains(event.target);\n if (scope.isOpen && !(dpContainsTarget || popupContainsTarget)) {\n scope.$apply(function() {\n scope.isOpen = false;\n });\n }\n }\n\n function inputKeydownBind(evt) {\n if (evt.which === 27 && scope.isOpen) {\n evt.preventDefault();\n evt.stopPropagation();\n scope.$apply(function() {\n scope.isOpen = false;\n });\n element[0].focus();\n } else if (evt.which === 40 && !scope.isOpen) {\n evt.preventDefault();\n evt.stopPropagation();\n scope.$apply(function() {\n scope.isOpen = true;\n });\n }\n }\n}])\n\n.directive('uibDatepickerPopup', function() {\n return {\n require: ['ngModel', 'uibDatepickerPopup'],\n controller: 'UibDatepickerPopupController',\n scope: {\n isOpen: '=?',\n currentText: '@',\n clearText: '@',\n closeText: '@',\n dateDisabled: '&',\n customClass: '&'\n },\n link: function(scope, element, attrs, ctrls) {\n var ngModel = ctrls[0],\n ctrl = ctrls[1];\n\n ctrl.init(ngModel);\n }\n };\n})\n\n.directive('uibDatepickerPopupWrap', function() {\n return {\n replace: true,\n transclude: true,\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/datepicker/popup.html';\n }\n };\n});\n\n/* Deprecated datepicker below */\n\nangular.module('ui.bootstrap.datepicker')\n\n.value('$datepickerSuppressWarning', false)\n\n.controller('DatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$log', 'dateFilter', 'uibDatepickerConfig', '$datepickerSuppressError', '$datepickerSuppressWarning', function($scope, $attrs, $parse, $interpolate, $log, dateFilter, datepickerConfig, $datepickerSuppressError, $datepickerSuppressWarning) {\n if (!$datepickerSuppressWarning) {\n $log.warn('DatepickerController is now deprecated. Use UibDatepickerController instead.');\n }\n\n var self = this,\n ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl;\n\n this.modes = ['day', 'month', 'year'];\n\n angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle',\n 'showWeeks', 'startingDay', 'yearRange', 'shortcutPropagation'], function(key, index) {\n self[key] = angular.isDefined($attrs[key]) ? (index < 6 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key];\n });\n\n angular.forEach(['minDate', 'maxDate'], function(key) {\n if ($attrs[key]) {\n $scope.$parent.$watch($parse($attrs[key]), function(value) {\n self[key] = value ? new Date(value) : null;\n self.refreshView();\n });\n } else {\n self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null;\n }\n });\n\n angular.forEach(['minMode', 'maxMode'], function(key) {\n if ($attrs[key]) {\n $scope.$parent.$watch($parse($attrs[key]), function(value) {\n self[key] = angular.isDefined(value) ? value : $attrs[key];\n $scope[key] = self[key];\n if ((key == 'minMode' && self.modes.indexOf($scope.datepickerMode) < self.modes.indexOf(self[key])) || (key == 'maxMode' && self.modes.indexOf($scope.datepickerMode) > self.modes.indexOf(self[key]))) {\n $scope.datepickerMode = self[key];\n }\n });\n } else {\n self[key] = datepickerConfig[key] || null;\n $scope[key] = self[key];\n }\n });\n\n $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode;\n $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);\n\n if (angular.isDefined($attrs.initDate)) {\n this.activeDate = $scope.$parent.$eval($attrs.initDate) || new Date();\n $scope.$parent.$watch($attrs.initDate, function(initDate) {\n if (initDate && (ngModelCtrl.$isEmpty(ngModelCtrl.$modelValue) || ngModelCtrl.$invalid)) {\n self.activeDate = initDate;\n self.refreshView();\n }\n });\n } else {\n this.activeDate = new Date();\n }\n\n $scope.isActive = function(dateObject) {\n if (self.compare(dateObject.date, self.activeDate) === 0) {\n $scope.activeDateId = dateObject.uid;\n return true;\n }\n return false;\n };\n\n this.init = function(ngModelCtrl_) {\n ngModelCtrl = ngModelCtrl_;\n\n ngModelCtrl.$render = function() {\n self.render();\n };\n };\n\n this.render = function() {\n if (ngModelCtrl.$viewValue) {\n var date = new Date(ngModelCtrl.$viewValue),\n isValid = !isNaN(date);\n\n if (isValid) {\n this.activeDate = date;\n } else if (!$datepickerSuppressError) {\n $log.error('Datepicker directive: \"ng-model\" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');\n }\n }\n this.refreshView();\n };\n\n this.refreshView = function() {\n if (this.element) {\n this._refreshView();\n\n var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;\n ngModelCtrl.$setValidity('dateDisabled', !date || (this.element && !this.isDisabled(date)));\n }\n };\n\n this.createDateObject = function(date, format) {\n var model = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;\n return {\n date: date,\n label: dateFilter(date, format),\n selected: model && this.compare(date, model) === 0,\n disabled: this.isDisabled(date),\n current: this.compare(date, new Date()) === 0,\n customClass: this.customClass(date)\n };\n };\n\n this.isDisabled = function(date) {\n return ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode})));\n };\n\n this.customClass = function(date) {\n return $scope.customClass({date: date, mode: $scope.datepickerMode});\n };\n\n // Split array into smaller arrays\n this.split = function(arr, size) {\n var arrays = [];\n while (arr.length > 0) {\n arrays.push(arr.splice(0, size));\n }\n return arrays;\n };\n\n this.fixTimeZone = function(date) {\n var hours = date.getHours();\n date.setHours(hours === 23 ? hours + 2 : 0);\n };\n\n $scope.select = function(date) {\n if ($scope.datepickerMode === self.minMode) {\n var dt = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : new Date(0, 0, 0, 0, 0, 0, 0);\n dt.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());\n ngModelCtrl.$setViewValue(dt);\n ngModelCtrl.$render();\n } else {\n self.activeDate = date;\n $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) - 1];\n }\n };\n\n $scope.move = function(direction) {\n var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),\n month = self.activeDate.getMonth() + direction * (self.step.months || 0);\n self.activeDate.setFullYear(year, month, 1);\n self.refreshView();\n };\n\n $scope.toggleMode = function(direction) {\n direction = direction || 1;\n\n if (($scope.datepickerMode === self.maxMode && direction === 1) || ($scope.datepickerMode === self.minMode && direction === -1)) {\n return;\n }\n\n $scope.datepickerMode = self.modes[self.modes.indexOf($scope.datepickerMode) + direction];\n };\n\n // Key event mapper\n $scope.keys = { 13: 'enter', 32: 'space', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home', 37: 'left', 38: 'up', 39: 'right', 40: 'down' };\n\n var focusElement = function() {\n self.element[0].focus();\n };\n\n $scope.$on('uib:datepicker.focus', focusElement);\n\n $scope.keydown = function(evt) {\n var key = $scope.keys[evt.which];\n\n if (!key || evt.shiftKey || evt.altKey) {\n return;\n }\n\n evt.preventDefault();\n if (!self.shortcutPropagation) {\n evt.stopPropagation();\n }\n\n if (key === 'enter' || key === 'space') {\n if (self.isDisabled(self.activeDate)) {\n return; // do nothing\n }\n $scope.select(self.activeDate);\n } else if (evt.ctrlKey && (key === 'up' || key === 'down')) {\n $scope.toggleMode(key === 'up' ? 1 : -1);\n } else {\n self.handleKeyDown(key, evt);\n self.refreshView();\n }\n };\n}])\n\n.directive('datepicker', ['$log', '$datepickerSuppressWarning', function($log, $datepickerSuppressWarning) {\n return {\n replace: true,\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/datepicker/datepicker.html';\n },\n scope: {\n datepickerMode: '=?',\n dateDisabled: '&',\n customClass: '&',\n shortcutPropagation: '&?'\n },\n require: ['datepicker', '^ngModel'],\n controller: 'DatepickerController',\n controllerAs: 'datepicker',\n link: function(scope, element, attrs, ctrls) {\n if (!$datepickerSuppressWarning) {\n $log.warn('datepicker is now deprecated. Use uib-datepicker instead.');\n }\n\n var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n datepickerCtrl.init(ngModelCtrl);\n }\n };\n}])\n\n.directive('daypicker', ['$log', '$datepickerSuppressWarning', function($log, $datepickerSuppressWarning) {\n return {\n replace: true,\n templateUrl: 'template/datepicker/day.html',\n require: ['^datepicker', 'daypicker'],\n controller: 'UibDaypickerController',\n link: function(scope, element, attrs, ctrls) {\n if (!$datepickerSuppressWarning) {\n $log.warn('daypicker is now deprecated. Use uib-daypicker instead.');\n }\n\n var datepickerCtrl = ctrls[0],\n daypickerCtrl = ctrls[1];\n\n daypickerCtrl.init(datepickerCtrl);\n }\n };\n}])\n\n.directive('monthpicker', ['$log', '$datepickerSuppressWarning', function($log, $datepickerSuppressWarning) {\n return {\n replace: true,\n templateUrl: 'template/datepicker/month.html',\n require: ['^datepicker', 'monthpicker'],\n controller: 'UibMonthpickerController',\n link: function(scope, element, attrs, ctrls) {\n if (!$datepickerSuppressWarning) {\n $log.warn('monthpicker is now deprecated. Use uib-monthpicker instead.');\n }\n\n var datepickerCtrl = ctrls[0],\n monthpickerCtrl = ctrls[1];\n\n monthpickerCtrl.init(datepickerCtrl);\n }\n };\n}])\n\n.directive('yearpicker', ['$log', '$datepickerSuppressWarning', function($log, $datepickerSuppressWarning) {\n return {\n replace: true,\n templateUrl: 'template/datepicker/year.html',\n require: ['^datepicker', 'yearpicker'],\n controller: 'UibYearpickerController',\n link: function(scope, element, attrs, ctrls) {\n if (!$datepickerSuppressWarning) {\n $log.warn('yearpicker is now deprecated. Use uib-yearpicker instead.');\n }\n\n var ctrl = ctrls[0];\n angular.extend(ctrl, ctrls[1]);\n ctrl.yearpickerInit();\n\n ctrl.refreshView();\n }\n };\n}])\n\n.directive('datepickerPopup', ['$log', '$datepickerSuppressWarning', function($log, $datepickerSuppressWarning) {\n return {\n require: ['ngModel', 'datepickerPopup'],\n controller: 'UibDatepickerPopupController',\n scope: {\n isOpen: '=?',\n currentText: '@',\n clearText: '@',\n closeText: '@',\n dateDisabled: '&',\n customClass: '&'\n },\n link: function(scope, element, attrs, ctrls) {\n if (!$datepickerSuppressWarning) {\n $log.warn('datepicker-popup is now deprecated. Use uib-datepicker-popup instead.');\n }\n\n var ngModel = ctrls[0],\n ctrl = ctrls[1];\n\n ctrl.init(ngModel);\n }\n };\n}])\n\n.directive('datepickerPopupWrap', ['$log', '$datepickerSuppressWarning', function($log, $datepickerSuppressWarning) {\n return {\n replace: true,\n transclude: true,\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/datepicker/popup.html';\n },\n link: function() {\n if (!$datepickerSuppressWarning) {\n $log.warn('datepicker-popup-wrap is now deprecated. Use uib-datepicker-popup-wrap instead.');\n }\n }\n };\n}]);\n\nangular.module('ui.bootstrap.dropdown', ['ui.bootstrap.position'])\n\n.constant('uibDropdownConfig', {\n openClass: 'open'\n})\n\n.service('uibDropdownService', ['$document', '$rootScope', function($document, $rootScope) {\n var openScope = null;\n\n this.open = function(dropdownScope) {\n if (!openScope) {\n $document.bind('click', closeDropdown);\n $document.bind('keydown', keybindFilter);\n }\n\n if (openScope && openScope !== dropdownScope) {\n openScope.isOpen = false;\n }\n\n openScope = dropdownScope;\n };\n\n this.close = function(dropdownScope) {\n if (openScope === dropdownScope) {\n openScope = null;\n $document.unbind('click', closeDropdown);\n $document.unbind('keydown', keybindFilter);\n }\n };\n\n var closeDropdown = function(evt) {\n // This method may still be called during the same mouse event that\n // unbound this event handler. So check openScope before proceeding.\n if (!openScope) { return; }\n\n if (evt && openScope.getAutoClose() === 'disabled') { return ; }\n\n var toggleElement = openScope.getToggleElement();\n if (evt && toggleElement && toggleElement[0].contains(evt.target)) {\n return;\n }\n\n var dropdownElement = openScope.getDropdownElement();\n if (evt && openScope.getAutoClose() === 'outsideClick' &&\n dropdownElement && dropdownElement[0].contains(evt.target)) {\n return;\n }\n\n openScope.isOpen = false;\n\n if (!$rootScope.$$phase) {\n openScope.$apply();\n }\n };\n\n var keybindFilter = function(evt) {\n if (evt.which === 27) {\n openScope.focusToggleElement();\n closeDropdown();\n } else if (openScope.isKeynavEnabled() && /(38|40)/.test(evt.which) && openScope.isOpen) {\n evt.preventDefault();\n evt.stopPropagation();\n openScope.focusDropdownEntry(evt.which);\n }\n };\n}])\n\n.controller('UibDropdownController', ['$scope', '$element', '$attrs', '$parse', 'uibDropdownConfig', 'uibDropdownService', '$animate', '$uibPosition', '$document', '$compile', '$templateRequest', function($scope, $element, $attrs, $parse, dropdownConfig, uibDropdownService, $animate, $position, $document, $compile, $templateRequest) {\n var self = this,\n scope = $scope.$new(), // create a child scope so we are not polluting original one\n templateScope,\n openClass = dropdownConfig.openClass,\n getIsOpen,\n setIsOpen = angular.noop,\n toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop,\n appendToBody = false,\n keynavEnabled =false,\n selectedOption = null;\n\n\n $element.addClass('dropdown');\n\n this.init = function() {\n if ($attrs.isOpen) {\n getIsOpen = $parse($attrs.isOpen);\n setIsOpen = getIsOpen.assign;\n\n $scope.$watch(getIsOpen, function(value) {\n scope.isOpen = !!value;\n });\n }\n\n appendToBody = angular.isDefined($attrs.dropdownAppendToBody);\n keynavEnabled = angular.isDefined($attrs.uibKeyboardNav);\n\n if (appendToBody && self.dropdownMenu) {\n $document.find('body').append(self.dropdownMenu);\n $element.on('$destroy', function handleDestroyEvent() {\n self.dropdownMenu.remove();\n });\n }\n };\n\n this.toggle = function(open) {\n return scope.isOpen = arguments.length ? !!open : !scope.isOpen;\n };\n\n // Allow other directives to watch status\n this.isOpen = function() {\n return scope.isOpen;\n };\n\n scope.getToggleElement = function() {\n return self.toggleElement;\n };\n\n scope.getAutoClose = function() {\n return $attrs.autoClose || 'always'; //or 'outsideClick' or 'disabled'\n };\n\n scope.getElement = function() {\n return $element;\n };\n\n scope.isKeynavEnabled = function() {\n return keynavEnabled;\n };\n\n scope.focusDropdownEntry = function(keyCode) {\n var elems = self.dropdownMenu ? //If append to body is used.\n (angular.element(self.dropdownMenu).find('a')) :\n (angular.element($element).find('ul').eq(0).find('a'));\n\n switch (keyCode) {\n case (40): {\n if (!angular.isNumber(self.selectedOption)) {\n self.selectedOption = 0;\n } else {\n self.selectedOption = (self.selectedOption === elems.length - 1 ?\n self.selectedOption :\n self.selectedOption + 1);\n }\n break;\n }\n case (38): {\n if (!angular.isNumber(self.selectedOption)) {\n self.selectedOption = elems.length - 1;\n } else {\n self.selectedOption = self.selectedOption === 0 ?\n 0 : self.selectedOption - 1;\n }\n break;\n }\n }\n elems[self.selectedOption].focus();\n };\n\n scope.getDropdownElement = function() {\n return self.dropdownMenu;\n };\n\n scope.focusToggleElement = function() {\n if (self.toggleElement) {\n self.toggleElement[0].focus();\n }\n };\n\n scope.$watch('isOpen', function(isOpen, wasOpen) {\n if (appendToBody && self.dropdownMenu) {\n var pos = $position.positionElements($element, self.dropdownMenu, 'bottom-left', true);\n var css = {\n top: pos.top + 'px',\n display: isOpen ? 'block' : 'none'\n };\n\n var rightalign = self.dropdownMenu.hasClass('dropdown-menu-right');\n if (!rightalign) {\n css.left = pos.left + 'px';\n css.right = 'auto';\n } else {\n css.left = 'auto';\n css.right = (window.innerWidth - (pos.left + $element.prop('offsetWidth'))) + 'px';\n }\n\n self.dropdownMenu.css(css);\n }\n\n $animate[isOpen ? 'addClass' : 'removeClass']($element, openClass).then(function() {\n if (angular.isDefined(isOpen) && isOpen !== wasOpen) {\n toggleInvoker($scope, { open: !!isOpen });\n }\n });\n\n if (isOpen) {\n if (self.dropdownMenuTemplateUrl) {\n $templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) {\n templateScope = scope.$new();\n $compile(tplContent.trim())(templateScope, function(dropdownElement) {\n var newEl = dropdownElement;\n self.dropdownMenu.replaceWith(newEl);\n self.dropdownMenu = newEl;\n });\n });\n }\n\n scope.focusToggleElement();\n uibDropdownService.open(scope);\n } else {\n if (self.dropdownMenuTemplateUrl) {\n if (templateScope) {\n templateScope.$destroy();\n }\n var newEl = angular.element('');\n self.dropdownMenu.replaceWith(newEl);\n self.dropdownMenu = newEl;\n }\n\n uibDropdownService.close(scope);\n self.selectedOption = null;\n }\n\n if (angular.isFunction(setIsOpen)) {\n setIsOpen($scope, isOpen);\n }\n });\n\n $scope.$on('$locationChangeSuccess', function() {\n if (scope.getAutoClose() !== 'disabled') {\n scope.isOpen = false;\n }\n });\n\n var offDestroy = $scope.$on('$destroy', function() {\n scope.$destroy();\n });\n scope.$on('$destroy', offDestroy);\n}])\n\n.directive('uibDropdown', function() {\n return {\n controller: 'UibDropdownController',\n link: function(scope, element, attrs, dropdownCtrl) {\n dropdownCtrl.init();\n }\n };\n})\n\n.directive('uibDropdownMenu', function() {\n return {\n restrict: 'AC',\n require: '?^uibDropdown',\n link: function(scope, element, attrs, dropdownCtrl) {\n if (!dropdownCtrl || angular.isDefined(attrs.dropdownNested)) {\n return;\n }\n\n element.addClass('dropdown-menu');\n\n var tplUrl = attrs.templateUrl;\n if (tplUrl) {\n dropdownCtrl.dropdownMenuTemplateUrl = tplUrl;\n }\n\n if (!dropdownCtrl.dropdownMenu) {\n dropdownCtrl.dropdownMenu = element;\n }\n }\n };\n})\n\n.directive('uibKeyboardNav', function() {\n return {\n restrict: 'A',\n require: '?^uibDropdown',\n link: function(scope, element, attrs, dropdownCtrl) {\n element.bind('keydown', function(e) {\n if ([38, 40].indexOf(e.which) !== -1) {\n e.preventDefault();\n e.stopPropagation();\n\n var elems = dropdownCtrl.dropdownMenu.find('a');\n\n switch (e.which) {\n case (40): { // Down\n if (!angular.isNumber(dropdownCtrl.selectedOption)) {\n dropdownCtrl.selectedOption = 0;\n } else {\n dropdownCtrl.selectedOption = dropdownCtrl.selectedOption === elems.length -1 ?\n dropdownCtrl.selectedOption : dropdownCtrl.selectedOption + 1;\n }\n break;\n }\n case (38): { // Up\n if (!angular.isNumber(dropdownCtrl.selectedOption)) {\n dropdownCtrl.selectedOption = elems.length - 1;\n } else {\n dropdownCtrl.selectedOption = dropdownCtrl.selectedOption === 0 ?\n 0 : dropdownCtrl.selectedOption - 1;\n }\n break;\n }\n }\n elems[dropdownCtrl.selectedOption].focus();\n }\n });\n }\n };\n})\n\n.directive('uibDropdownToggle', function() {\n return {\n require: '?^uibDropdown',\n link: function(scope, element, attrs, dropdownCtrl) {\n if (!dropdownCtrl) {\n return;\n }\n\n element.addClass('dropdown-toggle');\n\n dropdownCtrl.toggleElement = element;\n\n var toggleDropdown = function(event) {\n event.preventDefault();\n\n if (!element.hasClass('disabled') && !attrs.disabled) {\n scope.$apply(function() {\n dropdownCtrl.toggle();\n });\n }\n };\n\n element.bind('click', toggleDropdown);\n\n // WAI-ARIA\n element.attr({ 'aria-haspopup': true, 'aria-expanded': false });\n scope.$watch(dropdownCtrl.isOpen, function(isOpen) {\n element.attr('aria-expanded', !!isOpen);\n });\n\n scope.$on('$destroy', function() {\n element.unbind('click', toggleDropdown);\n });\n }\n };\n});\n\n/* Deprecated dropdown below */\n\nangular.module('ui.bootstrap.dropdown')\n\n.value('$dropdownSuppressWarning', false)\n\n.service('dropdownService', ['$log', '$dropdownSuppressWarning', 'uibDropdownService', function($log, $dropdownSuppressWarning, uibDropdownService) {\n if (!$dropdownSuppressWarning) {\n $log.warn('dropdownService is now deprecated. Use uibDropdownService instead.');\n }\n\n angular.extend(this, uibDropdownService);\n}])\n\n.controller('DropdownController', ['$scope', '$element', '$attrs', '$parse', 'uibDropdownConfig', 'uibDropdownService', '$animate', '$uibPosition', '$document', '$compile', '$templateRequest', '$log', '$dropdownSuppressWarning', function($scope, $element, $attrs, $parse, dropdownConfig, uibDropdownService, $animate, $position, $document, $compile, $templateRequest, $log, $dropdownSuppressWarning) {\n if (!$dropdownSuppressWarning) {\n $log.warn('DropdownController is now deprecated. Use UibDropdownController instead.');\n }\n\n var self = this,\n scope = $scope.$new(), // create a child scope so we are not polluting original one\n templateScope,\n openClass = dropdownConfig.openClass,\n getIsOpen,\n setIsOpen = angular.noop,\n toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop,\n appendToBody = false,\n keynavEnabled =false,\n selectedOption = null;\n\n\n $element.addClass('dropdown');\n\n this.init = function() {\n if ($attrs.isOpen) {\n getIsOpen = $parse($attrs.isOpen);\n setIsOpen = getIsOpen.assign;\n\n $scope.$watch(getIsOpen, function(value) {\n scope.isOpen = !!value;\n });\n }\n\n appendToBody = angular.isDefined($attrs.dropdownAppendToBody);\n keynavEnabled = angular.isDefined($attrs.uibKeyboardNav);\n\n if (appendToBody && self.dropdownMenu) {\n $document.find('body').append(self.dropdownMenu);\n $element.on('$destroy', function handleDestroyEvent() {\n self.dropdownMenu.remove();\n });\n }\n };\n\n this.toggle = function(open) {\n return scope.isOpen = arguments.length ? !!open : !scope.isOpen;\n };\n\n // Allow other directives to watch status\n this.isOpen = function() {\n return scope.isOpen;\n };\n\n scope.getToggleElement = function() {\n return self.toggleElement;\n };\n\n scope.getAutoClose = function() {\n return $attrs.autoClose || 'always'; //or 'outsideClick' or 'disabled'\n };\n\n scope.getElement = function() {\n return $element;\n };\n\n scope.isKeynavEnabled = function() {\n return keynavEnabled;\n };\n\n scope.focusDropdownEntry = function(keyCode) {\n var elems = self.dropdownMenu ? //If append to body is used.\n (angular.element(self.dropdownMenu).find('a')) :\n (angular.element($element).find('ul').eq(0).find('a'));\n\n switch (keyCode) {\n case (40): {\n if (!angular.isNumber(self.selectedOption)) {\n self.selectedOption = 0;\n } else {\n self.selectedOption = (self.selectedOption === elems.length -1 ?\n self.selectedOption :\n self.selectedOption + 1);\n }\n break;\n }\n case (38): {\n if (!angular.isNumber(self.selectedOption)) {\n self.selectedOption = elems.length - 1;\n } else {\n self.selectedOption = self.selectedOption === 0 ?\n 0 : self.selectedOption - 1;\n }\n break;\n }\n }\n elems[self.selectedOption].focus();\n };\n\n scope.getDropdownElement = function() {\n return self.dropdownMenu;\n };\n\n scope.focusToggleElement = function() {\n if (self.toggleElement) {\n self.toggleElement[0].focus();\n }\n };\n\n scope.$watch('isOpen', function(isOpen, wasOpen) {\n if (appendToBody && self.dropdownMenu) {\n var pos = $position.positionElements($element, self.dropdownMenu, 'bottom-left', true);\n var css = {\n top: pos.top + 'px',\n display: isOpen ? 'block' : 'none'\n };\n\n var rightalign = self.dropdownMenu.hasClass('dropdown-menu-right');\n if (!rightalign) {\n css.left = pos.left + 'px';\n css.right = 'auto';\n } else {\n css.left = 'auto';\n css.right = (window.innerWidth - (pos.left + $element.prop('offsetWidth'))) + 'px';\n }\n\n self.dropdownMenu.css(css);\n }\n\n $animate[isOpen ? 'addClass' : 'removeClass']($element, openClass).then(function() {\n if (angular.isDefined(isOpen) && isOpen !== wasOpen) {\n toggleInvoker($scope, { open: !!isOpen });\n }\n });\n\n if (isOpen) {\n if (self.dropdownMenuTemplateUrl) {\n $templateRequest(self.dropdownMenuTemplateUrl).then(function(tplContent) {\n templateScope = scope.$new();\n $compile(tplContent.trim())(templateScope, function(dropdownElement) {\n var newEl = dropdownElement;\n self.dropdownMenu.replaceWith(newEl);\n self.dropdownMenu = newEl;\n });\n });\n }\n\n scope.focusToggleElement();\n uibDropdownService.open(scope);\n } else {\n if (self.dropdownMenuTemplateUrl) {\n if (templateScope) {\n templateScope.$destroy();\n }\n var newEl = angular.element('');\n self.dropdownMenu.replaceWith(newEl);\n self.dropdownMenu = newEl;\n }\n\n uibDropdownService.close(scope);\n self.selectedOption = null;\n }\n\n if (angular.isFunction(setIsOpen)) {\n setIsOpen($scope, isOpen);\n }\n });\n\n $scope.$on('$locationChangeSuccess', function() {\n if (scope.getAutoClose() !== 'disabled') {\n scope.isOpen = false;\n }\n });\n\n var offDestroy = $scope.$on('$destroy', function() {\n scope.$destroy();\n });\n scope.$on('$destroy', offDestroy);\n}])\n\n.directive('dropdown', ['$log', '$dropdownSuppressWarning', function($log, $dropdownSuppressWarning) {\n return {\n controller: 'DropdownController',\n link: function(scope, element, attrs, dropdownCtrl) {\n if (!$dropdownSuppressWarning) {\n $log.warn('dropdown is now deprecated. Use uib-dropdown instead.');\n }\n\n dropdownCtrl.init();\n }\n };\n}])\n\n.directive('dropdownMenu', ['$log', '$dropdownSuppressWarning', function($log, $dropdownSuppressWarning) {\n return {\n restrict: 'AC',\n require: '?^dropdown',\n link: function(scope, element, attrs, dropdownCtrl) {\n if (!dropdownCtrl || angular.isDefined(attrs.dropdownNested)) {\n return;\n }\n\n if (!$dropdownSuppressWarning) {\n $log.warn('dropdown-menu is now deprecated. Use uib-dropdown-menu instead.');\n }\n\n element.addClass('dropdown-menu');\n\n var tplUrl = attrs.templateUrl;\n if (tplUrl) {\n dropdownCtrl.dropdownMenuTemplateUrl = tplUrl;\n }\n\n if (!dropdownCtrl.dropdownMenu) {\n dropdownCtrl.dropdownMenu = element;\n }\n }\n };\n}])\n\n.directive('keyboardNav', ['$log', '$dropdownSuppressWarning', function($log, $dropdownSuppressWarning) {\n return {\n restrict: 'A',\n require: '?^dropdown',\n link: function(scope, element, attrs, dropdownCtrl) {\n if (!$dropdownSuppressWarning) {\n $log.warn('keyboard-nav is now deprecated. Use uib-keyboard-nav instead.');\n }\n\n element.bind('keydown', function(e) {\n if ([38, 40].indexOf(e.which) !== -1) {\n e.preventDefault();\n e.stopPropagation();\n\n var elems = dropdownCtrl.dropdownMenu.find('a');\n\n switch (e.which) {\n case (40): { // Down\n if (!angular.isNumber(dropdownCtrl.selectedOption)) {\n dropdownCtrl.selectedOption = 0;\n } else {\n dropdownCtrl.selectedOption = dropdownCtrl.selectedOption === elems.length -1 ?\n dropdownCtrl.selectedOption : dropdownCtrl.selectedOption + 1;\n }\n break;\n }\n case (38): { // Up\n if (!angular.isNumber(dropdownCtrl.selectedOption)) {\n dropdownCtrl.selectedOption = elems.length - 1;\n } else {\n dropdownCtrl.selectedOption = dropdownCtrl.selectedOption === 0 ?\n 0 : dropdownCtrl.selectedOption - 1;\n }\n break;\n }\n }\n elems[dropdownCtrl.selectedOption].focus();\n }\n });\n }\n };\n}])\n\n.directive('dropdownToggle', ['$log', '$dropdownSuppressWarning', function($log, $dropdownSuppressWarning) {\n return {\n require: '?^dropdown',\n link: function(scope, element, attrs, dropdownCtrl) {\n if (!$dropdownSuppressWarning) {\n $log.warn('dropdown-toggle is now deprecated. Use uib-dropdown-toggle instead.');\n }\n\n if (!dropdownCtrl) {\n return;\n }\n\n element.addClass('dropdown-toggle');\n\n dropdownCtrl.toggleElement = element;\n\n var toggleDropdown = function(event) {\n event.preventDefault();\n\n if (!element.hasClass('disabled') && !attrs.disabled) {\n scope.$apply(function() {\n dropdownCtrl.toggle();\n });\n }\n };\n\n element.bind('click', toggleDropdown);\n\n // WAI-ARIA\n element.attr({ 'aria-haspopup': true, 'aria-expanded': false });\n scope.$watch(dropdownCtrl.isOpen, function(isOpen) {\n element.attr('aria-expanded', !!isOpen);\n });\n\n scope.$on('$destroy', function() {\n element.unbind('click', toggleDropdown);\n });\n }\n };\n}]);\n\nangular.module('ui.bootstrap.stackedMap', [])\n/**\n * A helper, internal data structure that acts as a map but also allows getting / removing\n * elements in the LIFO order\n */\n .factory('$$stackedMap', function() {\n return {\n createNew: function() {\n var stack = [];\n\n return {\n add: function(key, value) {\n stack.push({\n key: key,\n value: value\n });\n },\n get: function(key) {\n for (var i = 0; i < stack.length; i++) {\n if (key == stack[i].key) {\n return stack[i];\n }\n }\n },\n keys: function() {\n var keys = [];\n for (var i = 0; i < stack.length; i++) {\n keys.push(stack[i].key);\n }\n return keys;\n },\n top: function() {\n return stack[stack.length - 1];\n },\n remove: function(key) {\n var idx = -1;\n for (var i = 0; i < stack.length; i++) {\n if (key == stack[i].key) {\n idx = i;\n break;\n }\n }\n return stack.splice(idx, 1)[0];\n },\n removeTop: function() {\n return stack.splice(stack.length - 1, 1)[0];\n },\n length: function() {\n return stack.length;\n }\n };\n }\n };\n });\nangular.module('ui.bootstrap.modal', ['ui.bootstrap.stackedMap'])\n/**\n * A helper, internal data structure that stores all references attached to key\n */\n .factory('$$multiMap', function() {\n return {\n createNew: function() {\n var map = {};\n\n return {\n entries: function() {\n return Object.keys(map).map(function(key) {\n return {\n key: key,\n value: map[key]\n };\n });\n },\n get: function(key) {\n return map[key];\n },\n hasKey: function(key) {\n return !!map[key];\n },\n keys: function() {\n return Object.keys(map);\n },\n put: function(key, value) {\n if (!map[key]) {\n map[key] = [];\n }\n\n map[key].push(value);\n },\n remove: function(key, value) {\n var values = map[key];\n\n if (!values) {\n return;\n }\n\n var idx = values.indexOf(value);\n\n if (idx !== -1) {\n values.splice(idx, 1);\n }\n\n if (!values.length) {\n delete map[key];\n }\n }\n };\n }\n };\n })\n\n/**\n * A helper directive for the $modal service. It creates a backdrop element.\n */\n .directive('uibModalBackdrop', [\n '$animate', '$injector', '$uibModalStack',\n function($animate , $injector, $modalStack) {\n var $animateCss = null;\n\n if ($injector.has('$animateCss')) {\n $animateCss = $injector.get('$animateCss');\n }\n\n return {\n replace: true,\n templateUrl: 'template/modal/backdrop.html',\n compile: function(tElement, tAttrs) {\n tElement.addClass(tAttrs.backdropClass);\n return linkFn;\n }\n };\n\n function linkFn(scope, element, attrs) {\n // Temporary fix for prefixing\n element.addClass('modal-backdrop');\n\n if (attrs.modalInClass) {\n if ($animateCss) {\n $animateCss(element, {\n addClass: attrs.modalInClass\n }).start();\n } else {\n $animate.addClass(element, attrs.modalInClass);\n }\n\n scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {\n var done = setIsAsync();\n if ($animateCss) {\n $animateCss(element, {\n removeClass: attrs.modalInClass\n }).start().then(done);\n } else {\n $animate.removeClass(element, attrs.modalInClass).then(done);\n }\n });\n }\n }\n }])\n\n .directive('uibModalWindow', [\n '$uibModalStack', '$q', '$animate', '$injector',\n function($modalStack , $q , $animate, $injector) {\n var $animateCss = null;\n\n if ($injector.has('$animateCss')) {\n $animateCss = $injector.get('$animateCss');\n }\n\n return {\n scope: {\n index: '@'\n },\n replace: true,\n transclude: true,\n templateUrl: function(tElement, tAttrs) {\n return tAttrs.templateUrl || 'template/modal/window.html';\n },\n link: function(scope, element, attrs) {\n element.addClass(attrs.windowClass || '');\n element.addClass(attrs.windowTopClass || '');\n scope.size = attrs.size;\n\n scope.close = function(evt) {\n var modal = $modalStack.getTop();\n if (modal && modal.value.backdrop && modal.value.backdrop !== 'static' && (evt.target === evt.currentTarget)) {\n evt.preventDefault();\n evt.stopPropagation();\n $modalStack.dismiss(modal.key, 'backdrop click');\n }\n };\n\n // moved from template to fix issue #2280\n element.on('click', scope.close);\n\n // This property is only added to the scope for the purpose of detecting when this directive is rendered.\n // We can detect that by using this property in the template associated with this directive and then use\n // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.\n scope.$isRendered = true;\n\n // Deferred object that will be resolved when this modal is render.\n var modalRenderDeferObj = $q.defer();\n // Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready.\n // In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template.\n attrs.$observe('modalRender', function(value) {\n if (value == 'true') {\n modalRenderDeferObj.resolve();\n }\n });\n\n modalRenderDeferObj.promise.then(function() {\n var animationPromise = null;\n\n if (attrs.modalInClass) {\n if ($animateCss) {\n animationPromise = $animateCss(element, {\n addClass: attrs.modalInClass\n }).start();\n } else {\n animationPromise = $animate.addClass(element, attrs.modalInClass);\n }\n\n scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {\n var done = setIsAsync();\n if ($animateCss) {\n $animateCss(element, {\n removeClass: attrs.modalInClass\n }).start().then(done);\n } else {\n $animate.removeClass(element, attrs.modalInClass).then(done);\n }\n });\n }\n\n\n $q.when(animationPromise).then(function() {\n var inputWithAutofocus = element[0].querySelector('[autofocus]');\n /**\n * Auto-focusing of a freshly-opened modal element causes any child elements\n * with the autofocus attribute to lose focus. This is an issue on touch\n * based devices which will show and then hide the onscreen keyboard.\n * Attempts to refocus the autofocus element via JavaScript will not reopen\n * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus\n * the modal element if the modal does not contain an autofocus element.\n */\n if (inputWithAutofocus) {\n inputWithAutofocus.focus();\n } else {\n element[0].focus();\n }\n });\n\n // Notify {@link $modalStack} that modal is rendered.\n var modal = $modalStack.getTop();\n if (modal) {\n $modalStack.modalRendered(modal.key);\n }\n });\n }\n };\n }])\n\n .directive('uibModalAnimationClass', function() {\n return {\n compile: function(tElement, tAttrs) {\n if (tAttrs.modalAnimation) {\n tElement.addClass(tAttrs.uibModalAnimationClass);\n }\n }\n };\n })\n\n .directive('uibModalTransclude', function() {\n return {\n link: function($scope, $element, $attrs, controller, $transclude) {\n $transclude($scope.$parent, function(clone) {\n $element.empty();\n $element.append(clone);\n });\n }\n };\n })\n\n .factory('$uibModalStack', [\n '$animate', '$timeout', '$document', '$compile', '$rootScope',\n '$q',\n '$injector',\n '$$multiMap',\n '$$stackedMap',\n function($animate , $timeout , $document , $compile , $rootScope ,\n $q,\n $injector,\n $$multiMap,\n $$stackedMap) {\n var $animateCss = null;\n\n if ($injector.has('$animateCss')) {\n $animateCss = $injector.get('$animateCss');\n }\n\n var OPENED_MODAL_CLASS = 'modal-open';\n\n var backdropDomEl, backdropScope;\n var openedWindows = $$stackedMap.createNew();\n var openedClasses = $$multiMap.createNew();\n var $modalStack = {\n NOW_CLOSING_EVENT: 'modal.stack.now-closing'\n };\n\n //Modal focus behavior\n var focusableElementList;\n var focusIndex = 0;\n var tababbleSelector = 'a[href], area[href], input:not([disabled]), ' +\n 'button:not([disabled]),select:not([disabled]), textarea:not([disabled]), ' +\n 'iframe, object, embed, *[tabindex], *[contenteditable=true]';\n\n function backdropIndex() {\n var topBackdropIndex = -1;\n var opened = openedWindows.keys();\n for (var i = 0; i < opened.length; i++) {\n if (openedWindows.get(opened[i]).value.backdrop) {\n topBackdropIndex = i;\n }\n }\n return topBackdropIndex;\n }\n\n $rootScope.$watch(backdropIndex, function(newBackdropIndex) {\n if (backdropScope) {\n backdropScope.index = newBackdropIndex;\n }\n });\n\n function removeModalWindow(modalInstance, elementToReceiveFocus) {\n var body = $document.find('body').eq(0);\n var modalWindow = openedWindows.get(modalInstance).value;\n\n //clean up the stack\n openedWindows.remove(modalInstance);\n\n removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() {\n var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS;\n openedClasses.remove(modalBodyClass, modalInstance);\n body.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass));\n toggleTopWindowClass(true);\n });\n checkRemoveBackdrop();\n\n //move focus to specified element if available, or else to body\n if (elementToReceiveFocus && elementToReceiveFocus.focus) {\n elementToReceiveFocus.focus();\n } else {\n body.focus();\n }\n }\n\n // Add or remove \"windowTopClass\" from the top window in the stack\n function toggleTopWindowClass(toggleSwitch) {\n var modalWindow;\n\n if (openedWindows.length() > 0) {\n modalWindow = openedWindows.top().value;\n modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch);\n }\n }\n\n function checkRemoveBackdrop() {\n //remove backdrop if no longer needed\n if (backdropDomEl && backdropIndex() == -1) {\n var backdropScopeRef = backdropScope;\n removeAfterAnimate(backdropDomEl, backdropScope, function() {\n backdropScopeRef = null;\n });\n backdropDomEl = undefined;\n backdropScope = undefined;\n }\n }\n\n function removeAfterAnimate(domEl, scope, done) {\n var asyncDeferred;\n var asyncPromise = null;\n var setIsAsync = function() {\n if (!asyncDeferred) {\n asyncDeferred = $q.defer();\n asyncPromise = asyncDeferred.promise;\n }\n\n return function asyncDone() {\n asyncDeferred.resolve();\n };\n };\n scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync);\n\n // Note that it's intentional that asyncPromise might be null.\n // That's when setIsAsync has not been called during the\n // NOW_CLOSING_EVENT broadcast.\n return $q.when(asyncPromise).then(afterAnimating);\n\n function afterAnimating() {\n if (afterAnimating.done) {\n return;\n }\n afterAnimating.done = true;\n\n if ($animateCss) {\n $animateCss(domEl, {\n event: 'leave'\n }).start().then(function() {\n domEl.remove();\n });\n } else {\n $animate.leave(domEl);\n }\n scope.$destroy();\n if (done) {\n done();\n }\n }\n }\n\n $document.bind('keydown', function(evt) {\n if (evt.isDefaultPrevented()) {\n return evt;\n }\n\n var modal = openedWindows.top();\n if (modal && modal.value.keyboard) {\n switch (evt.which) {\n case 27: {\n evt.preventDefault();\n $rootScope.$apply(function() {\n $modalStack.dismiss(modal.key, 'escape key press');\n });\n break;\n }\n case 9: {\n $modalStack.loadFocusElementList(modal);\n var focusChanged = false;\n if (evt.shiftKey) {\n if ($modalStack.isFocusInFirstItem(evt)) {\n focusChanged = $modalStack.focusLastFocusableElement();\n }\n } else {\n if ($modalStack.isFocusInLastItem(evt)) {\n focusChanged = $modalStack.focusFirstFocusableElement();\n }\n }\n\n if (focusChanged) {\n evt.preventDefault();\n evt.stopPropagation();\n }\n break;\n }\n }\n }\n });\n\n $modalStack.open = function(modalInstance, modal) {\n var modalOpener = $document[0].activeElement,\n modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS;\n\n toggleTopWindowClass(false);\n\n openedWindows.add(modalInstance, {\n deferred: modal.deferred,\n renderDeferred: modal.renderDeferred,\n modalScope: modal.scope,\n backdrop: modal.backdrop,\n keyboard: modal.keyboard,\n openedClass: modal.openedClass,\n windowTopClass: modal.windowTopClass\n });\n\n openedClasses.put(modalBodyClass, modalInstance);\n\n var body = $document.find('body').eq(0),\n currBackdropIndex = backdropIndex();\n\n if (currBackdropIndex >= 0 && !backdropDomEl) {\n backdropScope = $rootScope.$new(true);\n backdropScope.index = currBackdropIndex;\n var angularBackgroundDomEl = angular.element('');\n angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass);\n if (modal.animation) {\n angularBackgroundDomEl.attr('modal-animation', 'true');\n }\n backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope);\n body.append(backdropDomEl);\n }\n\n var angularDomEl = angular.element('');\n angularDomEl.attr({\n 'template-url': modal.windowTemplateUrl,\n 'window-class': modal.windowClass,\n 'window-top-class': modal.windowTopClass,\n 'size': modal.size,\n 'index': openedWindows.length() - 1,\n 'animate': 'animate'\n }).html(modal.content);\n if (modal.animation) {\n angularDomEl.attr('modal-animation', 'true');\n }\n\n var modalDomEl = $compile(angularDomEl)(modal.scope);\n openedWindows.top().value.modalDomEl = modalDomEl;\n openedWindows.top().value.modalOpener = modalOpener;\n body.append(modalDomEl);\n body.addClass(modalBodyClass);\n\n $modalStack.clearFocusListCache();\n };\n\n function broadcastClosing(modalWindow, resultOrReason, closing) {\n return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented;\n }\n\n $modalStack.close = function(modalInstance, result) {\n var modalWindow = openedWindows.get(modalInstance);\n if (modalWindow && broadcastClosing(modalWindow, result, true)) {\n modalWindow.value.modalScope.$$uibDestructionScheduled = true;\n modalWindow.value.deferred.resolve(result);\n removeModalWindow(modalInstance, modalWindow.value.modalOpener);\n return true;\n }\n return !modalWindow;\n };\n\n $modalStack.dismiss = function(modalInstance, reason) {\n var modalWindow = openedWindows.get(modalInstance);\n if (modalWindow && broadcastClosing(modalWindow, reason, false)) {\n modalWindow.value.modalScope.$$uibDestructionScheduled = true;\n modalWindow.value.deferred.reject(reason);\n removeModalWindow(modalInstance, modalWindow.value.modalOpener);\n return true;\n }\n return !modalWindow;\n };\n\n $modalStack.dismissAll = function(reason) {\n var topModal = this.getTop();\n while (topModal && this.dismiss(topModal.key, reason)) {\n topModal = this.getTop();\n }\n };\n\n $modalStack.getTop = function() {\n return openedWindows.top();\n };\n\n $modalStack.modalRendered = function(modalInstance) {\n var modalWindow = openedWindows.get(modalInstance);\n if (modalWindow) {\n modalWindow.value.renderDeferred.resolve();\n }\n };\n\n $modalStack.focusFirstFocusableElement = function() {\n if (focusableElementList.length > 0) {\n focusableElementList[0].focus();\n return true;\n }\n return false;\n };\n $modalStack.focusLastFocusableElement = function() {\n if (focusableElementList.length > 0) {\n focusableElementList[focusableElementList.length - 1].focus();\n return true;\n }\n return false;\n };\n\n $modalStack.isFocusInFirstItem = function(evt) {\n if (focusableElementList.length > 0) {\n return (evt.target || evt.srcElement) == focusableElementList[0];\n }\n return false;\n };\n\n $modalStack.isFocusInLastItem = function(evt) {\n if (focusableElementList.length > 0) {\n return (evt.target || evt.srcElement) == focusableElementList[focusableElementList.length - 1];\n }\n return false;\n };\n\n $modalStack.clearFocusListCache = function() {\n focusableElementList = [];\n focusIndex = 0;\n };\n\n $modalStack.loadFocusElementList = function(modalWindow) {\n if (focusableElementList === undefined || !focusableElementList.length) {\n if (modalWindow) {\n var modalDomE1 = modalWindow.value.modalDomEl;\n if (modalDomE1 && modalDomE1.length) {\n focusableElementList = modalDomE1[0].querySelectorAll(tababbleSelector);\n }\n }\n }\n };\n\n return $modalStack;\n }])\n\n .provider('$uibModal', function() {\n var $modalProvider = {\n options: {\n animation: true,\n backdrop: true, //can also be false or 'static'\n keyboard: true\n },\n $get: ['$injector', '$rootScope', '$q', '$templateRequest', '$controller', '$uibModalStack', '$modalSuppressWarning', '$log',\n function ($injector, $rootScope, $q, $templateRequest, $controller, $modalStack, $modalSuppressWarning, $log) {\n var $modal = {};\n\n function getTemplatePromise(options) {\n return options.template ? $q.when(options.template) :\n $templateRequest(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl);\n }\n\n function getResolvePromises(resolves) {\n var promisesArr = [];\n angular.forEach(resolves, function(value) {\n if (angular.isFunction(value) || angular.isArray(value)) {\n promisesArr.push($q.when($injector.invoke(value)));\n } else if (angular.isString(value)) {\n promisesArr.push($q.when($injector.get(value)));\n } else {\n promisesArr.push($q.when(value));\n }\n });\n return promisesArr;\n }\n\n var promiseChain = null;\n $modal.getPromiseChain = function() {\n return promiseChain;\n };\n\n $modal.open = function(modalOptions) {\n var modalResultDeferred = $q.defer();\n var modalOpenedDeferred = $q.defer();\n var modalRenderDeferred = $q.defer();\n\n //prepare an instance of a modal to be injected into controllers and returned to a caller\n var modalInstance = {\n result: modalResultDeferred.promise,\n opened: modalOpenedDeferred.promise,\n rendered: modalRenderDeferred.promise,\n close: function (result) {\n return $modalStack.close(modalInstance, result);\n },\n dismiss: function (reason) {\n return $modalStack.dismiss(modalInstance, reason);\n }\n };\n\n //merge and clean up options\n modalOptions = angular.extend({}, $modalProvider.options, modalOptions);\n modalOptions.resolve = modalOptions.resolve || {};\n\n //verify options\n if (!modalOptions.template && !modalOptions.templateUrl) {\n throw new Error('One of template or templateUrl options is required.');\n }\n\n var templateAndResolvePromise =\n $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve)));\n\n function resolveWithTemplate() {\n return templateAndResolvePromise;\n }\n\n // Wait for the resolution of the existing promise chain.\n // Then switch to our own combined promise dependency (regardless of how the previous modal fared).\n // Then add to $modalStack and resolve opened.\n // Finally clean up the chain variable if no subsequent modal has overwritten it.\n var samePromise;\n samePromise = promiseChain = $q.all([promiseChain])\n .then(resolveWithTemplate, resolveWithTemplate)\n .then(function resolveSuccess(tplAndVars) {\n\n var modalScope = (modalOptions.scope || $rootScope).$new();\n modalScope.$close = modalInstance.close;\n modalScope.$dismiss = modalInstance.dismiss;\n\n modalScope.$on('$destroy', function() {\n if (!modalScope.$$uibDestructionScheduled) {\n modalScope.$dismiss('$uibUnscheduledDestruction');\n }\n });\n\n var ctrlInstance, ctrlLocals = {};\n var resolveIter = 1;\n\n //controllers\n if (modalOptions.controller) {\n ctrlLocals.$scope = modalScope;\n ctrlLocals.$uibModalInstance = modalInstance;\n Object.defineProperty(ctrlLocals, '$modalInstance', {\n get: function() {\n if (!$modalSuppressWarning) {\n $log.warn('$modalInstance is now deprecated. Use $uibModalInstance instead.');\n }\n\n return modalInstance;\n }\n });\n angular.forEach(modalOptions.resolve, function(value, key) {\n ctrlLocals[key] = tplAndVars[resolveIter++];\n });\n\n ctrlInstance = $controller(modalOptions.controller, ctrlLocals);\n if (modalOptions.controllerAs) {\n if (modalOptions.bindToController) {\n angular.extend(ctrlInstance, modalScope);\n }\n\n modalScope[modalOptions.controllerAs] = ctrlInstance;\n }\n }\n\n $modalStack.open(modalInstance, {\n scope: modalScope,\n deferred: modalResultDeferred,\n renderDeferred: modalRenderDeferred,\n content: tplAndVars[0],\n animation: modalOptions.animation,\n backdrop: modalOptions.backdrop,\n keyboard: modalOptions.keyboard,\n backdropClass: modalOptions.backdropClass,\n windowTopClass: modalOptions.windowTopClass,\n windowClass: modalOptions.windowClass,\n windowTemplateUrl: modalOptions.windowTemplateUrl,\n size: modalOptions.size,\n openedClass: modalOptions.openedClass\n });\n modalOpenedDeferred.resolve(true);\n\n }, function resolveError(reason) {\n modalOpenedDeferred.reject(reason);\n modalResultDeferred.reject(reason);\n })\n .finally(function() {\n if (promiseChain === samePromise) {\n promiseChain = null;\n }\n });\n\n return modalInstance;\n };\n\n return $modal;\n }\n ]\n };\n\n return $modalProvider;\n });\n\n/* deprecated modal below */\n\nangular.module('ui.bootstrap.modal')\n\n .value('$modalSuppressWarning', false)\n\n /**\n * A helper directive for the $modal service. It creates a backdrop element.\n */\n .directive('modalBackdrop', [\n '$animate', '$injector', '$modalStack', '$log', '$modalSuppressWarning',\n function($animate , $injector, $modalStack, $log, $modalSuppressWarning) {\n var $animateCss = null;\n\n if ($injector.has('$animateCss')) {\n $animateCss = $injector.get('$animateCss');\n }\n\n return {\n replace: true,\n templateUrl: 'template/modal/backdrop.html',\n compile: function(tElement, tAttrs) {\n tElement.addClass(tAttrs.backdropClass);\n return linkFn;\n }\n };\n\n function linkFn(scope, element, attrs) {\n if (!$modalSuppressWarning) {\n $log.warn('modal-backdrop is now deprecated. Use uib-modal-backdrop instead.');\n }\n element.addClass('modal-backdrop');\n\n if (attrs.modalInClass) {\n if ($animateCss) {\n $animateCss(element, {\n addClass: attrs.modalInClass\n }).start();\n } else {\n $animate.addClass(element, attrs.modalInClass);\n }\n\n scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {\n var done = setIsAsync();\n if ($animateCss) {\n $animateCss(element, {\n removeClass: attrs.modalInClass\n }).start().then(done);\n } else {\n $animate.removeClass(element, attrs.modalInClass).then(done);\n }\n });\n }\n }\n }])\n\n .directive('modalWindow', [\n '$modalStack', '$q', '$animate', '$injector', '$log', '$modalSuppressWarning',\n function($modalStack , $q , $animate, $injector, $log, $modalSuppressWarning) {\n var $animateCss = null;\n\n if ($injector.has('$animateCss')) {\n $animateCss = $injector.get('$animateCss');\n }\n\n return {\n scope: {\n index: '@'\n },\n replace: true,\n transclude: true,\n templateUrl: function(tElement, tAttrs) {\n return tAttrs.templateUrl || 'template/modal/window.html';\n },\n link: function(scope, element, attrs) {\n if (!$modalSuppressWarning) {\n $log.warn('modal-window is now deprecated. Use uib-modal-window instead.');\n }\n element.addClass(attrs.windowClass || '');\n element.addClass(attrs.windowTopClass || '');\n scope.size = attrs.size;\n\n scope.close = function(evt) {\n var modal = $modalStack.getTop();\n if (modal && modal.value.backdrop && modal.value.backdrop !== 'static' && (evt.target === evt.currentTarget)) {\n evt.preventDefault();\n evt.stopPropagation();\n $modalStack.dismiss(modal.key, 'backdrop click');\n }\n };\n\n // moved from template to fix issue #2280\n element.on('click', scope.close);\n\n // This property is only added to the scope for the purpose of detecting when this directive is rendered.\n // We can detect that by using this property in the template associated with this directive and then use\n // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}.\n scope.$isRendered = true;\n\n // Deferred object that will be resolved when this modal is render.\n var modalRenderDeferObj = $q.defer();\n // Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready.\n // In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template.\n attrs.$observe('modalRender', function(value) {\n if (value == 'true') {\n modalRenderDeferObj.resolve();\n }\n });\n\n modalRenderDeferObj.promise.then(function() {\n var animationPromise = null;\n\n if (attrs.modalInClass) {\n if ($animateCss) {\n animationPromise = $animateCss(element, {\n addClass: attrs.modalInClass\n }).start();\n } else {\n animationPromise = $animate.addClass(element, attrs.modalInClass);\n }\n\n scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) {\n var done = setIsAsync();\n if ($animateCss) {\n $animateCss(element, {\n removeClass: attrs.modalInClass\n }).start().then(done);\n } else {\n $animate.removeClass(element, attrs.modalInClass).then(done);\n }\n });\n }\n\n\n $q.when(animationPromise).then(function() {\n var inputWithAutofocus = element[0].querySelector('[autofocus]');\n /**\n * Auto-focusing of a freshly-opened modal element causes any child elements\n * with the autofocus attribute to lose focus. This is an issue on touch\n * based devices which will show and then hide the onscreen keyboard.\n * Attempts to refocus the autofocus element via JavaScript will not reopen\n * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus\n * the modal element if the modal does not contain an autofocus element.\n */\n if (inputWithAutofocus) {\n inputWithAutofocus.focus();\n } else {\n element[0].focus();\n }\n });\n\n // Notify {@link $modalStack} that modal is rendered.\n var modal = $modalStack.getTop();\n if (modal) {\n $modalStack.modalRendered(modal.key);\n }\n });\n }\n };\n }])\n\n .directive('modalAnimationClass', [\n '$log', '$modalSuppressWarning',\n function ($log, $modalSuppressWarning) {\n return {\n compile: function(tElement, tAttrs) {\n if (!$modalSuppressWarning) {\n $log.warn('modal-animation-class is now deprecated. Use uib-modal-animation-class instead.');\n }\n if (tAttrs.modalAnimation) {\n tElement.addClass(tAttrs.modalAnimationClass);\n }\n }\n };\n }])\n\n .directive('modalTransclude', [\n '$log', '$modalSuppressWarning',\n function ($log, $modalSuppressWarning) {\n return {\n link: function($scope, $element, $attrs, controller, $transclude) {\n if (!$modalSuppressWarning) {\n $log.warn('modal-transclude is now deprecated. Use uib-modal-transclude instead.');\n }\n $transclude($scope.$parent, function(clone) {\n $element.empty();\n $element.append(clone);\n });\n }\n };\n }])\n\n .service('$modalStack', [\n '$animate', '$timeout', '$document', '$compile', '$rootScope',\n '$q',\n '$injector',\n '$$multiMap',\n '$$stackedMap',\n '$uibModalStack',\n '$log',\n '$modalSuppressWarning',\n function($animate , $timeout , $document , $compile , $rootScope ,\n $q,\n $injector,\n $$multiMap,\n $$stackedMap,\n $uibModalStack,\n $log,\n $modalSuppressWarning) {\n if (!$modalSuppressWarning) {\n $log.warn('$modalStack is now deprecated. Use $uibModalStack instead.');\n }\n\n angular.extend(this, $uibModalStack);\n }])\n\n .provider('$modal', ['$uibModalProvider', function($uibModalProvider) {\n angular.extend(this, $uibModalProvider);\n\n this.$get = ['$injector', '$log', '$modalSuppressWarning',\n function ($injector, $log, $modalSuppressWarning) {\n if (!$modalSuppressWarning) {\n $log.warn('$modal is now deprecated. Use $uibModal instead.');\n }\n\n return $injector.invoke($uibModalProvider.$get);\n }];\n }]);\n\nangular.module('ui.bootstrap.pagination', [])\n.controller('UibPaginationController', ['$scope', '$attrs', '$parse', function($scope, $attrs, $parse) {\n var self = this,\n ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl\n setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;\n\n this.init = function(ngModelCtrl_, config) {\n ngModelCtrl = ngModelCtrl_;\n this.config = config;\n\n ngModelCtrl.$render = function() {\n self.render();\n };\n\n if ($attrs.itemsPerPage) {\n $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) {\n self.itemsPerPage = parseInt(value, 10);\n $scope.totalPages = self.calculateTotalPages();\n });\n } else {\n this.itemsPerPage = config.itemsPerPage;\n }\n\n $scope.$watch('totalItems', function() {\n $scope.totalPages = self.calculateTotalPages();\n });\n\n $scope.$watch('totalPages', function(value) {\n setNumPages($scope.$parent, value); // Readonly variable\n\n if ( $scope.page > value ) {\n $scope.selectPage(value);\n } else {\n ngModelCtrl.$render();\n }\n });\n };\n\n this.calculateTotalPages = function() {\n var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage);\n return Math.max(totalPages || 0, 1);\n };\n\n this.render = function() {\n $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1;\n };\n\n $scope.selectPage = function(page, evt) {\n if (evt) {\n evt.preventDefault();\n }\n\n var clickAllowed = !$scope.ngDisabled || !evt;\n if (clickAllowed && $scope.page !== page && page > 0 && page <= $scope.totalPages) {\n if (evt && evt.target) {\n evt.target.blur();\n }\n ngModelCtrl.$setViewValue(page);\n ngModelCtrl.$render();\n }\n };\n\n $scope.getText = function(key) {\n return $scope[key + 'Text'] || self.config[key + 'Text'];\n };\n\n $scope.noPrevious = function() {\n return $scope.page === 1;\n };\n\n $scope.noNext = function() {\n return $scope.page === $scope.totalPages;\n };\n}])\n\n.constant('uibPaginationConfig', {\n itemsPerPage: 10,\n boundaryLinks: false,\n directionLinks: true,\n firstText: 'First',\n previousText: 'Previous',\n nextText: 'Next',\n lastText: 'Last',\n rotate: true\n})\n\n.directive('uibPagination', ['$parse', 'uibPaginationConfig', function($parse, paginationConfig) {\n return {\n restrict: 'EA',\n scope: {\n totalItems: '=',\n firstText: '@',\n previousText: '@',\n nextText: '@',\n lastText: '@',\n ngDisabled:'='\n },\n require: ['uibPagination', '?ngModel'],\n controller: 'UibPaginationController',\n controllerAs: 'pagination',\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/pagination/pagination.html';\n },\n replace: true,\n link: function(scope, element, attrs, ctrls) {\n var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n if (!ngModelCtrl) {\n return; // do nothing if no ng-model\n }\n\n // Setup configuration parameters\n var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize,\n rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate;\n scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks;\n scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks;\n\n paginationCtrl.init(ngModelCtrl, paginationConfig);\n\n if (attrs.maxSize) {\n scope.$parent.$watch($parse(attrs.maxSize), function(value) {\n maxSize = parseInt(value, 10);\n paginationCtrl.render();\n });\n }\n\n // Create page object used in template\n function makePage(number, text, isActive) {\n return {\n number: number,\n text: text,\n active: isActive\n };\n }\n\n function getPages(currentPage, totalPages) {\n var pages = [];\n\n // Default page limits\n var startPage = 1, endPage = totalPages;\n var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages;\n\n // recompute if maxSize\n if (isMaxSized) {\n if (rotate) {\n // Current page is displayed in the middle of the visible ones\n startPage = Math.max(currentPage - Math.floor(maxSize/2), 1);\n endPage = startPage + maxSize - 1;\n\n // Adjust if limit is exceeded\n if (endPage > totalPages) {\n endPage = totalPages;\n startPage = endPage - maxSize + 1;\n }\n } else {\n // Visible pages are paginated with maxSize\n startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1;\n\n // Adjust last page if limit is exceeded\n endPage = Math.min(startPage + maxSize - 1, totalPages);\n }\n }\n\n // Add page number links\n for (var number = startPage; number <= endPage; number++) {\n var page = makePage(number, number, number === currentPage);\n pages.push(page);\n }\n\n // Add links to move between page sets\n if (isMaxSized && ! rotate) {\n if (startPage > 1) {\n var previousPageSet = makePage(startPage - 1, '...', false);\n pages.unshift(previousPageSet);\n }\n\n if (endPage < totalPages) {\n var nextPageSet = makePage(endPage + 1, '...', false);\n pages.push(nextPageSet);\n }\n }\n\n return pages;\n }\n\n var originalRender = paginationCtrl.render;\n paginationCtrl.render = function() {\n originalRender();\n if (scope.page > 0 && scope.page <= scope.totalPages) {\n scope.pages = getPages(scope.page, scope.totalPages);\n }\n };\n }\n };\n}])\n\n.constant('uibPagerConfig', {\n itemsPerPage: 10,\n previousText: '« Previous',\n nextText: 'Next »',\n align: true\n})\n\n.directive('uibPager', ['uibPagerConfig', function(pagerConfig) {\n return {\n restrict: 'EA',\n scope: {\n totalItems: '=',\n previousText: '@',\n nextText: '@',\n ngDisabled: '='\n },\n require: ['uibPager', '?ngModel'],\n controller: 'UibPaginationController',\n controllerAs: 'pagination',\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/pagination/pager.html';\n },\n replace: true,\n link: function(scope, element, attrs, ctrls) {\n var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n if (!ngModelCtrl) {\n return; // do nothing if no ng-model\n }\n\n scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align;\n paginationCtrl.init(ngModelCtrl, pagerConfig);\n }\n };\n}]);\n\n/* Deprecated Pagination Below */\n\nangular.module('ui.bootstrap.pagination')\n.value('$paginationSuppressWarning', false)\n.controller('PaginationController', ['$scope', '$attrs', '$parse', '$log', '$paginationSuppressWarning', function($scope, $attrs, $parse, $log, $paginationSuppressWarning) {\n if (!$paginationSuppressWarning) {\n $log.warn('PaginationController is now deprecated. Use UibPaginationController instead.');\n }\n\n var self = this,\n ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl\n setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;\n\n this.init = function(ngModelCtrl_, config) {\n ngModelCtrl = ngModelCtrl_;\n this.config = config;\n\n ngModelCtrl.$render = function() {\n self.render();\n };\n\n if ($attrs.itemsPerPage) {\n $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) {\n self.itemsPerPage = parseInt(value, 10);\n $scope.totalPages = self.calculateTotalPages();\n });\n } else {\n this.itemsPerPage = config.itemsPerPage;\n }\n\n $scope.$watch('totalItems', function() {\n $scope.totalPages = self.calculateTotalPages();\n });\n\n $scope.$watch('totalPages', function(value) {\n setNumPages($scope.$parent, value); // Readonly variable\n\n if ( $scope.page > value ) {\n $scope.selectPage(value);\n } else {\n ngModelCtrl.$render();\n }\n });\n };\n\n this.calculateTotalPages = function() {\n var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage);\n return Math.max(totalPages || 0, 1);\n };\n\n this.render = function() {\n $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1;\n };\n\n $scope.selectPage = function(page, evt) {\n if (evt) {\n evt.preventDefault();\n }\n\n var clickAllowed = !$scope.ngDisabled || !evt;\n if (clickAllowed && $scope.page !== page && page > 0 && page <= $scope.totalPages) {\n if (evt && evt.target) {\n evt.target.blur();\n }\n ngModelCtrl.$setViewValue(page);\n ngModelCtrl.$render();\n }\n };\n\n $scope.getText = function(key) {\n return $scope[key + 'Text'] || self.config[key + 'Text'];\n };\n\n $scope.noPrevious = function() {\n return $scope.page === 1;\n };\n\n $scope.noNext = function() {\n return $scope.page === $scope.totalPages;\n };\n}])\n.directive('pagination', ['$parse', 'uibPaginationConfig', '$log', '$paginationSuppressWarning', function($parse, paginationConfig, $log, $paginationSuppressWarning) {\n return {\n restrict: 'EA',\n scope: {\n totalItems: '=',\n firstText: '@',\n previousText: '@',\n nextText: '@',\n lastText: '@',\n ngDisabled:'='\n },\n require: ['pagination', '?ngModel'],\n controller: 'PaginationController',\n controllerAs: 'pagination',\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/pagination/pagination.html';\n },\n replace: true,\n link: function(scope, element, attrs, ctrls) {\n if (!$paginationSuppressWarning) {\n $log.warn('pagination is now deprecated. Use uib-pagination instead.');\n }\n var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n if (!ngModelCtrl) {\n return; // do nothing if no ng-model\n }\n\n // Setup configuration parameters\n var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize,\n rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate;\n scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks;\n scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks;\n\n paginationCtrl.init(ngModelCtrl, paginationConfig);\n\n if (attrs.maxSize) {\n scope.$parent.$watch($parse(attrs.maxSize), function(value) {\n maxSize = parseInt(value, 10);\n paginationCtrl.render();\n });\n }\n\n // Create page object used in template\n function makePage(number, text, isActive) {\n return {\n number: number,\n text: text,\n active: isActive\n };\n }\n\n function getPages(currentPage, totalPages) {\n var pages = [];\n\n // Default page limits\n var startPage = 1, endPage = totalPages;\n var isMaxSized = angular.isDefined(maxSize) && maxSize < totalPages;\n\n // recompute if maxSize\n if (isMaxSized) {\n if (rotate) {\n // Current page is displayed in the middle of the visible ones\n startPage = Math.max(currentPage - Math.floor(maxSize/2), 1);\n endPage = startPage + maxSize - 1;\n\n // Adjust if limit is exceeded\n if (endPage > totalPages) {\n endPage = totalPages;\n startPage = endPage - maxSize + 1;\n }\n } else {\n // Visible pages are paginated with maxSize\n startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1;\n\n // Adjust last page if limit is exceeded\n endPage = Math.min(startPage + maxSize - 1, totalPages);\n }\n }\n\n // Add page number links\n for (var number = startPage; number <= endPage; number++) {\n var page = makePage(number, number, number === currentPage);\n pages.push(page);\n }\n\n // Add links to move between page sets\n if (isMaxSized && ! rotate) {\n if (startPage > 1) {\n var previousPageSet = makePage(startPage - 1, '...', false);\n pages.unshift(previousPageSet);\n }\n\n if (endPage < totalPages) {\n var nextPageSet = makePage(endPage + 1, '...', false);\n pages.push(nextPageSet);\n }\n }\n\n return pages;\n }\n\n var originalRender = paginationCtrl.render;\n paginationCtrl.render = function() {\n originalRender();\n if (scope.page > 0 && scope.page <= scope.totalPages) {\n scope.pages = getPages(scope.page, scope.totalPages);\n }\n };\n }\n };\n}])\n\n.directive('pager', ['uibPagerConfig', '$log', '$paginationSuppressWarning', function(pagerConfig, $log, $paginationSuppressWarning) {\n return {\n restrict: 'EA',\n scope: {\n totalItems: '=',\n previousText: '@',\n nextText: '@',\n ngDisabled: '='\n },\n require: ['pager', '?ngModel'],\n controller: 'PaginationController',\n controllerAs: 'pagination',\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/pagination/pager.html';\n },\n replace: true,\n link: function(scope, element, attrs, ctrls) {\n if (!$paginationSuppressWarning) {\n $log.warn('pager is now deprecated. Use uib-pager instead.');\n }\n var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n if (!ngModelCtrl) {\n return; // do nothing if no ng-model\n }\n\n scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align;\n paginationCtrl.init(ngModelCtrl, pagerConfig);\n }\n };\n}]);\n\n/**\n * The following features are still outstanding: animation as a\n * function, placement as a function, inside, support for more triggers than\n * just mouse enter/leave, html tooltips, and selector delegation.\n */\nangular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.stackedMap'])\n\n/**\n * The $tooltip service creates tooltip- and popover-like directives as well as\n * houses global options for them.\n */\n.provider('$uibTooltip', function() {\n // The default options tooltip and popover.\n var defaultOptions = {\n placement: 'top',\n animation: true,\n popupDelay: 0,\n popupCloseDelay: 0,\n useContentExp: false\n };\n\n // Default hide triggers for each show trigger\n var triggerMap = {\n 'mouseenter': 'mouseleave',\n 'click': 'click',\n 'focus': 'blur',\n 'none': ''\n };\n\n // The options specified to the provider globally.\n var globalOptions = {};\n\n /**\n * `options({})` allows global configuration of all tooltips in the\n * application.\n *\n * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {\n * // place tooltips left instead of top by default\n * $tooltipProvider.options( { placement: 'left' } );\n * });\n */\n\tthis.options = function(value) {\n\t\tangular.extend(globalOptions, value);\n\t};\n\n /**\n * This allows you to extend the set of trigger mappings available. E.g.:\n *\n * $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );\n */\n this.setTriggers = function setTriggers(triggers) {\n angular.extend(triggerMap, triggers);\n };\n\n /**\n * This is a helper function for translating camel-case to snake-case.\n */\n function snake_case(name) {\n var regexp = /[A-Z]/g;\n var separator = '-';\n return name.replace(regexp, function(letter, pos) {\n return (pos ? separator : '') + letter.toLowerCase();\n });\n }\n\n /**\n * Returns the actual instance of the $tooltip service.\n * TODO support multiple triggers\n */\n this.$get = ['$window', '$compile', '$timeout', '$document', '$uibPosition', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) {\n var openedTooltips = $$stackedMap.createNew();\n $document.on('keypress', function(e) {\n if (e.which === 27) {\n var last = openedTooltips.top();\n if (last) {\n last.value.close();\n openedTooltips.removeTop();\n last = null;\n }\n }\n });\n\n return function $tooltip(ttType, prefix, defaultTriggerShow, options) {\n options = angular.extend({}, defaultOptions, globalOptions, options);\n\n /**\n * Returns an object of show and hide triggers.\n *\n * If a trigger is supplied,\n * it is used to show the tooltip; otherwise, it will use the `trigger`\n * option passed to the `$tooltipProvider.options` method; else it will\n * default to the trigger supplied to this directive factory.\n *\n * The hide trigger is based on the show trigger. If the `trigger` option\n * was passed to the `$tooltipProvider.options` method, it will use the\n * mapped trigger from `triggerMap` or the passed trigger if the map is\n * undefined; otherwise, it uses the `triggerMap` value of the show\n * trigger; else it will just use the show trigger.\n */\n function getTriggers(trigger) {\n var show = (trigger || options.trigger || defaultTriggerShow).split(' ');\n var hide = show.map(function(trigger) {\n return triggerMap[trigger] || trigger;\n });\n return {\n show: show,\n hide: hide\n };\n }\n\n var directiveName = snake_case(ttType);\n\n var startSym = $interpolate.startSymbol();\n var endSym = $interpolate.endSymbol();\n var template =\n '' +\n '
';\n\n return {\n compile: function(tElem, tAttrs) {\n var tooltipLinker = $compile(template);\n\n return function link(scope, element, attrs, tooltipCtrl) {\n var tooltip;\n var tooltipLinkedScope;\n var transitionTimeout;\n var showTimeout;\n var hideTimeout;\n var positionTimeout;\n var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;\n var triggers = getTriggers(undefined);\n var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);\n var ttScope = scope.$new(true);\n var repositionScheduled = false;\n var isOpenParse = angular.isDefined(attrs[prefix + 'IsOpen']) ? $parse(attrs[prefix + 'IsOpen']) : false;\n var contentParse = options.useContentExp ? $parse(attrs[ttType]) : false;\n var observers = [];\n\n var positionTooltip = function() {\n // check if tooltip exists and is not empty\n if (!tooltip || !tooltip.html()) { return; }\n\n if (!positionTimeout) {\n positionTimeout = $timeout(function() {\n // Reset the positioning.\n tooltip.css({ top: 0, left: 0 });\n\n // Now set the calculated positioning.\n var ttCss = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);\n ttCss.top += 'px';\n ttCss.left += 'px';\n ttCss.visibility = 'visible';\n tooltip.css(ttCss);\n\n positionTimeout = null;\n }, 0, false);\n }\n };\n\n // Set up the correct scope to allow transclusion later\n ttScope.origScope = scope;\n\n // By default, the tooltip is not open.\n // TODO add ability to start tooltip opened\n ttScope.isOpen = false;\n openedTooltips.add(ttScope, {\n close: hide\n });\n\n function toggleTooltipBind() {\n if (!ttScope.isOpen) {\n showTooltipBind();\n } else {\n hideTooltipBind();\n }\n }\n\n // Show the tooltip with delay if specified, otherwise show it immediately\n function showTooltipBind() {\n if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {\n return;\n }\n\n cancelHide();\n prepareTooltip();\n\n if (ttScope.popupDelay) {\n // Do nothing if the tooltip was already scheduled to pop-up.\n // This happens if show is triggered multiple times before any hide is triggered.\n if (!showTimeout) {\n showTimeout = $timeout(show, ttScope.popupDelay, false);\n }\n } else {\n show();\n }\n }\n\n function hideTooltipBind() {\n cancelShow();\n\n if (ttScope.popupCloseDelay) {\n if (!hideTimeout) {\n hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false);\n }\n } else {\n hide();\n }\n }\n\n // Show the tooltip popup element.\n function show() {\n cancelShow();\n cancelHide();\n\n // Don't show empty tooltips.\n if (!ttScope.content) {\n return angular.noop;\n }\n\n createTooltip();\n\n // And show the tooltip.\n ttScope.$evalAsync(function() {\n ttScope.isOpen = true;\n assignIsOpen(true);\n positionTooltip();\n });\n }\n\n function cancelShow() {\n if (showTimeout) {\n $timeout.cancel(showTimeout);\n showTimeout = null;\n }\n\n if (positionTimeout) {\n $timeout.cancel(positionTimeout);\n positionTimeout = null;\n }\n }\n\n // Hide the tooltip popup element.\n function hide() {\n cancelShow();\n cancelHide();\n\n if (!ttScope) {\n return;\n }\n\n // First things first: we don't show it anymore.\n ttScope.$evalAsync(function() {\n ttScope.isOpen = false;\n assignIsOpen(false);\n // And now we remove it from the DOM. However, if we have animation, we\n // need to wait for it to expire beforehand.\n // FIXME: this is a placeholder for a port of the transitions library.\n // The fade transition in TWBS is 150ms.\n if (ttScope.animation) {\n if (!transitionTimeout) {\n transitionTimeout = $timeout(removeTooltip, 150, false);\n }\n } else {\n removeTooltip();\n }\n });\n }\n\n function cancelHide() {\n if (hideTimeout) {\n $timeout.cancel(hideTimeout);\n hideTimeout = null;\n }\n if (transitionTimeout) {\n $timeout.cancel(transitionTimeout);\n transitionTimeout = null;\n }\n }\n\n function createTooltip() {\n // There can only be one tooltip element per directive shown at once.\n if (tooltip) {\n return;\n }\n\n tooltipLinkedScope = ttScope.$new();\n tooltip = tooltipLinker(tooltipLinkedScope, function(tooltip) {\n if (appendToBody) {\n $document.find('body').append(tooltip);\n } else {\n element.after(tooltip);\n }\n });\n\n prepObservers();\n }\n\n function removeTooltip() {\n unregisterObservers();\n\n transitionTimeout = null;\n if (tooltip) {\n tooltip.remove();\n tooltip = null;\n }\n if (tooltipLinkedScope) {\n tooltipLinkedScope.$destroy();\n tooltipLinkedScope = null;\n }\n }\n\n /**\n * Set the inital scope values. Once\n * the tooltip is created, the observers\n * will be added to keep things in synch.\n */\n function prepareTooltip() {\n ttScope.title = attrs[prefix + 'Title'];\n if (contentParse) {\n ttScope.content = contentParse(scope);\n } else {\n ttScope.content = attrs[ttType];\n }\n\n ttScope.popupClass = attrs[prefix + 'Class'];\n ttScope.placement = angular.isDefined(attrs[prefix + 'Placement']) ? attrs[prefix + 'Placement'] : options.placement;\n\n var delay = parseInt(attrs[prefix + 'PopupDelay'], 10);\n var closeDelay = parseInt(attrs[prefix + 'PopupCloseDelay'], 10);\n ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay;\n ttScope.popupCloseDelay = !isNaN(closeDelay) ? closeDelay : options.popupCloseDelay;\n }\n\n function assignIsOpen(isOpen) {\n if (isOpenParse && angular.isFunction(isOpenParse.assign)) {\n isOpenParse.assign(scope, isOpen);\n }\n }\n\n ttScope.contentExp = function() {\n return ttScope.content;\n };\n\n /**\n * Observe the relevant attributes.\n */\n attrs.$observe('disabled', function(val) {\n if (val) {\n cancelShow();\n }\n\n if (val && ttScope.isOpen) {\n hide();\n }\n });\n\n if (isOpenParse) {\n scope.$watch(isOpenParse, function(val) {\n /*jshint -W018 */\n if (ttScope && !val === ttScope.isOpen) {\n toggleTooltipBind();\n }\n /*jshint +W018 */\n });\n }\n\n function prepObservers() {\n observers.length = 0;\n\n if (contentParse) {\n observers.push(\n scope.$watch(contentParse, function(val) {\n ttScope.content = val;\n if (!val && ttScope.isOpen) {\n hide();\n }\n })\n );\n\n observers.push(\n tooltipLinkedScope.$watch(function() {\n if (!repositionScheduled) {\n repositionScheduled = true;\n tooltipLinkedScope.$$postDigest(function() {\n repositionScheduled = false;\n if (ttScope && ttScope.isOpen) {\n positionTooltip();\n }\n });\n }\n })\n );\n } else {\n observers.push(\n attrs.$observe(ttType, function(val) {\n ttScope.content = val;\n if (!val && ttScope.isOpen) {\n hide();\n } else {\n positionTooltip();\n }\n })\n );\n }\n\n observers.push(\n attrs.$observe(prefix + 'Title', function(val) {\n ttScope.title = val;\n if (ttScope.isOpen) {\n positionTooltip();\n }\n })\n );\n\n observers.push(\n attrs.$observe(prefix + 'Placement', function(val) {\n ttScope.placement = val ? val : options.placement;\n if (ttScope.isOpen) {\n positionTooltip();\n }\n })\n );\n }\n\n function unregisterObservers() {\n if (observers.length) {\n angular.forEach(observers, function(observer) {\n observer();\n });\n observers.length = 0;\n }\n }\n\n var unregisterTriggers = function() {\n triggers.show.forEach(function(trigger) {\n element.unbind(trigger, showTooltipBind);\n });\n triggers.hide.forEach(function(trigger) {\n trigger.split(' ').forEach(function(hideTrigger) {\n element[0].removeEventListener(hideTrigger, hideTooltipBind);\n });\n });\n };\n\n function prepTriggers() {\n var val = attrs[prefix + 'Trigger'];\n unregisterTriggers();\n\n triggers = getTriggers(val);\n\n if (triggers.show !== 'none') {\n triggers.show.forEach(function(trigger, idx) {\n // Using raw addEventListener due to jqLite/jQuery bug - #4060\n if (trigger === triggers.hide[idx]) {\n element[0].addEventListener(trigger, toggleTooltipBind);\n } else if (trigger) {\n element[0].addEventListener(trigger, showTooltipBind);\n triggers.hide[idx].split(' ').forEach(function(trigger) {\n element[0].addEventListener(trigger, hideTooltipBind);\n });\n }\n\n element.on('keypress', function(e) {\n if (e.which === 27) {\n hideTooltipBind();\n }\n });\n });\n }\n }\n\n prepTriggers();\n\n var animation = scope.$eval(attrs[prefix + 'Animation']);\n ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;\n\n var appendToBodyVal = scope.$eval(attrs[prefix + 'AppendToBody']);\n appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;\n\n // if a tooltip is attached to we need to remove it on\n // location change as its parent scope will probably not be destroyed\n // by the change.\n if (appendToBody) {\n scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess() {\n if (ttScope.isOpen) {\n hide();\n }\n });\n }\n\n // Make sure tooltip is destroyed and removed.\n scope.$on('$destroy', function onDestroyTooltip() {\n cancelShow();\n cancelHide();\n unregisterTriggers();\n removeTooltip();\n openedTooltips.remove(ttScope);\n ttScope = null;\n });\n };\n }\n };\n };\n }];\n})\n\n// This is mostly ngInclude code but with a custom scope\n.directive('uibTooltipTemplateTransclude', [\n '$animate', '$sce', '$compile', '$templateRequest',\nfunction ($animate , $sce , $compile , $templateRequest) {\n return {\n link: function(scope, elem, attrs) {\n var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope);\n\n var changeCounter = 0,\n currentScope,\n previousElement,\n currentElement;\n\n var cleanupLastIncludeContent = function() {\n if (previousElement) {\n previousElement.remove();\n previousElement = null;\n }\n\n if (currentScope) {\n currentScope.$destroy();\n currentScope = null;\n }\n\n if (currentElement) {\n $animate.leave(currentElement).then(function() {\n previousElement = null;\n });\n previousElement = currentElement;\n currentElement = null;\n }\n };\n\n scope.$watch($sce.parseAsResourceUrl(attrs.uibTooltipTemplateTransclude), function(src) {\n var thisChangeId = ++changeCounter;\n\n if (src) {\n //set the 2nd param to true to ignore the template request error so that the inner\n //contents and scope can be cleaned up.\n $templateRequest(src, true).then(function(response) {\n if (thisChangeId !== changeCounter) { return; }\n var newScope = origScope.$new();\n var template = response;\n\n var clone = $compile(template)(newScope, function(clone) {\n cleanupLastIncludeContent();\n $animate.enter(clone, elem);\n });\n\n currentScope = newScope;\n currentElement = clone;\n\n currentScope.$emit('$includeContentLoaded', src);\n }, function() {\n if (thisChangeId === changeCounter) {\n cleanupLastIncludeContent();\n scope.$emit('$includeContentError', src);\n }\n });\n scope.$emit('$includeContentRequested', src);\n } else {\n cleanupLastIncludeContent();\n }\n });\n\n scope.$on('$destroy', cleanupLastIncludeContent);\n }\n };\n}])\n\n/**\n * Note that it's intentional that these classes are *not* applied through $animate.\n * They must not be animated as they're expected to be present on the tooltip on\n * initialization.\n */\n.directive('uibTooltipClasses', function() {\n return {\n restrict: 'A',\n link: function(scope, element, attrs) {\n if (scope.placement) {\n element.addClass(scope.placement);\n }\n\n if (scope.popupClass) {\n element.addClass(scope.popupClass);\n }\n\n if (scope.animation()) {\n element.addClass(attrs.tooltipAnimationClass);\n }\n }\n };\n})\n\n.directive('uibTooltipPopup', function() {\n return {\n replace: true,\n scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },\n templateUrl: 'template/tooltip/tooltip-popup.html',\n link: function(scope, element) {\n element.addClass('tooltip');\n }\n };\n})\n\n.directive('uibTooltip', [ '$uibTooltip', function($uibTooltip) {\n return $uibTooltip('uibTooltip', 'tooltip', 'mouseenter');\n}])\n\n.directive('uibTooltipTemplatePopup', function() {\n return {\n replace: true,\n scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',\n originScope: '&' },\n templateUrl: 'template/tooltip/tooltip-template-popup.html',\n link: function(scope, element) {\n element.addClass('tooltip');\n }\n };\n})\n\n.directive('uibTooltipTemplate', ['$uibTooltip', function($uibTooltip) {\n return $uibTooltip('uibTooltipTemplate', 'tooltip', 'mouseenter', {\n useContentExp: true\n });\n}])\n\n.directive('uibTooltipHtmlPopup', function() {\n return {\n replace: true,\n scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },\n templateUrl: 'template/tooltip/tooltip-html-popup.html',\n link: function(scope, element) {\n element.addClass('tooltip');\n }\n };\n})\n\n.directive('uibTooltipHtml', ['$uibTooltip', function($uibTooltip) {\n return $uibTooltip('uibTooltipHtml', 'tooltip', 'mouseenter', {\n useContentExp: true\n });\n}]);\n\n/* Deprecated tooltip below */\n\nangular.module('ui.bootstrap.tooltip')\n\n.value('$tooltipSuppressWarning', false)\n\n.provider('$tooltip', ['$uibTooltipProvider', function($uibTooltipProvider) {\n angular.extend(this, $uibTooltipProvider);\n\n this.$get = ['$log', '$tooltipSuppressWarning', '$injector', function($log, $tooltipSuppressWarning, $injector) {\n if (!$tooltipSuppressWarning) {\n $log.warn('$tooltip is now deprecated. Use $uibTooltip instead.');\n }\n\n return $injector.invoke($uibTooltipProvider.$get);\n }];\n}])\n\n// This is mostly ngInclude code but with a custom scope\n.directive('tooltipTemplateTransclude', [\n '$animate', '$sce', '$compile', '$templateRequest', '$log', '$tooltipSuppressWarning',\nfunction ($animate , $sce , $compile , $templateRequest, $log, $tooltipSuppressWarning) {\n return {\n link: function(scope, elem, attrs) {\n if (!$tooltipSuppressWarning) {\n $log.warn('tooltip-template-transclude is now deprecated. Use uib-tooltip-template-transclude instead.');\n }\n\n var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope);\n\n var changeCounter = 0,\n currentScope,\n previousElement,\n currentElement;\n\n var cleanupLastIncludeContent = function() {\n if (previousElement) {\n previousElement.remove();\n previousElement = null;\n }\n if (currentScope) {\n currentScope.$destroy();\n currentScope = null;\n }\n if (currentElement) {\n $animate.leave(currentElement).then(function() {\n previousElement = null;\n });\n previousElement = currentElement;\n currentElement = null;\n }\n };\n\n scope.$watch($sce.parseAsResourceUrl(attrs.tooltipTemplateTransclude), function(src) {\n var thisChangeId = ++changeCounter;\n\n if (src) {\n //set the 2nd param to true to ignore the template request error so that the inner\n //contents and scope can be cleaned up.\n $templateRequest(src, true).then(function(response) {\n if (thisChangeId !== changeCounter) { return; }\n var newScope = origScope.$new();\n var template = response;\n\n var clone = $compile(template)(newScope, function(clone) {\n cleanupLastIncludeContent();\n $animate.enter(clone, elem);\n });\n\n currentScope = newScope;\n currentElement = clone;\n\n currentScope.$emit('$includeContentLoaded', src);\n }, function() {\n if (thisChangeId === changeCounter) {\n cleanupLastIncludeContent();\n scope.$emit('$includeContentError', src);\n }\n });\n scope.$emit('$includeContentRequested', src);\n } else {\n cleanupLastIncludeContent();\n }\n });\n\n scope.$on('$destroy', cleanupLastIncludeContent);\n }\n };\n}])\n\n.directive('tooltipClasses', ['$log', '$tooltipSuppressWarning', function($log, $tooltipSuppressWarning) {\n return {\n restrict: 'A',\n link: function(scope, element, attrs) {\n if (!$tooltipSuppressWarning) {\n $log.warn('tooltip-classes is now deprecated. Use uib-tooltip-classes instead.');\n }\n\n if (scope.placement) {\n element.addClass(scope.placement);\n }\n if (scope.popupClass) {\n element.addClass(scope.popupClass);\n }\n if (scope.animation()) {\n element.addClass(attrs.tooltipAnimationClass);\n }\n }\n };\n}])\n\n.directive('tooltipPopup', ['$log', '$tooltipSuppressWarning', function($log, $tooltipSuppressWarning) {\n return {\n replace: true,\n scope: { content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },\n templateUrl: 'template/tooltip/tooltip-popup.html',\n link: function(scope, element) {\n if (!$tooltipSuppressWarning) {\n $log.warn('tooltip-popup is now deprecated. Use uib-tooltip-popup instead.');\n }\n\n element.addClass('tooltip');\n }\n };\n}])\n\n.directive('tooltip', ['$tooltip', function($tooltip) {\n return $tooltip('tooltip', 'tooltip', 'mouseenter');\n}])\n\n.directive('tooltipTemplatePopup', ['$log', '$tooltipSuppressWarning', function($log, $tooltipSuppressWarning) {\n return {\n replace: true,\n scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',\n originScope: '&' },\n templateUrl: 'template/tooltip/tooltip-template-popup.html',\n link: function(scope, element) {\n if (!$tooltipSuppressWarning) {\n $log.warn('tooltip-template-popup is now deprecated. Use uib-tooltip-template-popup instead.');\n }\n\n element.addClass('tooltip');\n }\n };\n}])\n\n.directive('tooltipTemplate', ['$tooltip', function($tooltip) {\n return $tooltip('tooltipTemplate', 'tooltip', 'mouseenter', {\n useContentExp: true\n });\n}])\n\n.directive('tooltipHtmlPopup', ['$log', '$tooltipSuppressWarning', function($log, $tooltipSuppressWarning) {\n return {\n replace: true,\n scope: { contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },\n templateUrl: 'template/tooltip/tooltip-html-popup.html',\n link: function(scope, element) {\n if (!$tooltipSuppressWarning) {\n $log.warn('tooltip-html-popup is now deprecated. Use uib-tooltip-html-popup instead.');\n }\n\n element.addClass('tooltip');\n }\n };\n}])\n\n.directive('tooltipHtml', ['$tooltip', function($tooltip) {\n return $tooltip('tooltipHtml', 'tooltip', 'mouseenter', {\n useContentExp: true\n });\n}]);\n\n/**\n * The following features are still outstanding: popup delay, animation as a\n * function, placement as a function, inside, support for more triggers than\n * just mouse enter/leave, and selector delegatation.\n */\nangular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip'])\n\n.directive('uibPopoverTemplatePopup', function() {\n return {\n replace: true,\n scope: { title: '@', contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',\n originScope: '&' },\n templateUrl: 'template/popover/popover-template.html',\n link: function(scope, element) {\n element.addClass('popover');\n }\n };\n})\n\n.directive('uibPopoverTemplate', ['$uibTooltip', function($uibTooltip) {\n return $uibTooltip('uibPopoverTemplate', 'popover', 'click', {\n useContentExp: true\n });\n}])\n\n.directive('uibPopoverHtmlPopup', function() {\n return {\n replace: true,\n scope: { contentExp: '&', title: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },\n templateUrl: 'template/popover/popover-html.html',\n link: function(scope, element) {\n element.addClass('popover');\n }\n };\n})\n\n.directive('uibPopoverHtml', ['$uibTooltip', function($uibTooltip) {\n return $uibTooltip('uibPopoverHtml', 'popover', 'click', {\n useContentExp: true\n });\n}])\n\n.directive('uibPopoverPopup', function() {\n return {\n replace: true,\n scope: { title: '@', content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },\n templateUrl: 'template/popover/popover.html',\n link: function(scope, element) {\n element.addClass('popover');\n }\n };\n})\n\n.directive('uibPopover', ['$uibTooltip', function($uibTooltip) {\n return $uibTooltip('uibPopover', 'popover', 'click');\n}]);\n\n/* Deprecated popover below */\n\nangular.module('ui.bootstrap.popover')\n\n.value('$popoverSuppressWarning', false)\n\n.directive('popoverTemplatePopup', ['$log', '$popoverSuppressWarning', function($log, $popoverSuppressWarning) {\n return {\n replace: true,\n scope: { title: '@', contentExp: '&', placement: '@', popupClass: '@', animation: '&', isOpen: '&',\n originScope: '&' },\n templateUrl: 'template/popover/popover-template.html',\n link: function(scope, element) {\n if (!$popoverSuppressWarning) {\n $log.warn('popover-template-popup is now deprecated. Use uib-popover-template-popup instead.');\n }\n\n element.addClass('popover');\n }\n };\n}])\n\n.directive('popoverTemplate', ['$tooltip', function($tooltip) {\n return $tooltip('popoverTemplate', 'popover', 'click', {\n useContentExp: true\n });\n}])\n\n.directive('popoverHtmlPopup', ['$log', '$popoverSuppressWarning', function($log, $popoverSuppressWarning) {\n return {\n replace: true,\n scope: { contentExp: '&', title: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },\n templateUrl: 'template/popover/popover-html.html',\n link: function(scope, element) {\n if (!$popoverSuppressWarning) {\n $log.warn('popover-html-popup is now deprecated. Use uib-popover-html-popup instead.');\n }\n\n element.addClass('popover');\n }\n };\n}])\n\n.directive('popoverHtml', ['$tooltip', function($tooltip) {\n return $tooltip('popoverHtml', 'popover', 'click', {\n useContentExp: true\n });\n}])\n\n.directive('popoverPopup', ['$log', '$popoverSuppressWarning', function($log, $popoverSuppressWarning) {\n return {\n replace: true,\n scope: { title: '@', content: '@', placement: '@', popupClass: '@', animation: '&', isOpen: '&' },\n templateUrl: 'template/popover/popover.html',\n link: function(scope, element) {\n if (!$popoverSuppressWarning) {\n $log.warn('popover-popup is now deprecated. Use uib-popover-popup instead.');\n }\n\n element.addClass('popover');\n }\n };\n}])\n\n.directive('popover', ['$tooltip', function($tooltip) {\n\n return $tooltip('popover', 'popover', 'click');\n}]);\n\nangular.module('ui.bootstrap.progressbar', [])\n\n.constant('uibProgressConfig', {\n animate: true,\n max: 100\n})\n\n.controller('UibProgressController', ['$scope', '$attrs', 'uibProgressConfig', function($scope, $attrs, progressConfig) {\n var self = this,\n animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;\n\n this.bars = [];\n $scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max;\n\n this.addBar = function(bar, element, attrs) {\n if (!animate) {\n element.css({'transition': 'none'});\n }\n\n this.bars.push(bar);\n\n bar.max = $scope.max;\n bar.title = attrs && angular.isDefined(attrs.title) ? attrs.title : 'progressbar';\n\n bar.$watch('value', function(value) {\n bar.recalculatePercentage();\n });\n\n bar.recalculatePercentage = function() {\n var totalPercentage = self.bars.reduce(function(total, bar) {\n bar.percent = +(100 * bar.value / bar.max).toFixed(2);\n return total + bar.percent;\n }, 0);\n\n if (totalPercentage > 100) {\n bar.percent -= totalPercentage - 100;\n }\n };\n\n bar.$on('$destroy', function() {\n element = null;\n self.removeBar(bar);\n });\n };\n\n this.removeBar = function(bar) {\n this.bars.splice(this.bars.indexOf(bar), 1);\n this.bars.forEach(function (bar) {\n bar.recalculatePercentage();\n });\n };\n\n $scope.$watch('max', function(max) {\n self.bars.forEach(function(bar) {\n bar.max = $scope.max;\n bar.recalculatePercentage();\n });\n });\n}])\n\n.directive('uibProgress', function() {\n return {\n replace: true,\n transclude: true,\n controller: 'UibProgressController',\n require: 'uibProgress',\n scope: {\n max: '=?'\n },\n templateUrl: 'template/progressbar/progress.html'\n };\n})\n\n.directive('uibBar', function() {\n return {\n replace: true,\n transclude: true,\n require: '^uibProgress',\n scope: {\n value: '=',\n type: '@'\n },\n templateUrl: 'template/progressbar/bar.html',\n link: function(scope, element, attrs, progressCtrl) {\n progressCtrl.addBar(scope, element, attrs);\n }\n };\n})\n\n.directive('uibProgressbar', function() {\n return {\n replace: true,\n transclude: true,\n controller: 'UibProgressController',\n scope: {\n value: '=',\n max: '=?',\n type: '@'\n },\n templateUrl: 'template/progressbar/progressbar.html',\n link: function(scope, element, attrs, progressCtrl) {\n progressCtrl.addBar(scope, angular.element(element.children()[0]), {title: attrs.title});\n }\n };\n});\n\n/* Deprecated progressbar below */\n\nangular.module('ui.bootstrap.progressbar')\n\n.value('$progressSuppressWarning', false)\n\n.controller('ProgressController', ['$scope', '$attrs', 'uibProgressConfig', '$log', '$progressSuppressWarning', function($scope, $attrs, progressConfig, $log, $progressSuppressWarning) {\n if (!$progressSuppressWarning) {\n $log.warn('ProgressController is now deprecated. Use UibProgressController instead.');\n }\n\n var self = this,\n animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;\n\n this.bars = [];\n $scope.max = angular.isDefined($scope.max) ? $scope.max : progressConfig.max;\n\n this.addBar = function(bar, element, attrs) {\n if (!animate) {\n element.css({'transition': 'none'});\n }\n\n this.bars.push(bar);\n\n bar.max = $scope.max;\n bar.title = attrs && angular.isDefined(attrs.title) ? attrs.title : 'progressbar';\n\n bar.$watch('value', function(value) {\n bar.recalculatePercentage();\n });\n\n bar.recalculatePercentage = function() {\n bar.percent = +(100 * bar.value / bar.max).toFixed(2);\n\n var totalPercentage = self.bars.reduce(function(total, bar) {\n return total + bar.percent;\n }, 0);\n\n if (totalPercentage > 100) {\n bar.percent -= totalPercentage - 100;\n }\n };\n\n bar.$on('$destroy', function() {\n element = null;\n self.removeBar(bar);\n });\n };\n\n this.removeBar = function(bar) {\n this.bars.splice(this.bars.indexOf(bar), 1);\n };\n\n $scope.$watch('max', function(max) {\n self.bars.forEach(function(bar) {\n bar.max = $scope.max;\n bar.recalculatePercentage();\n });\n });\n}])\n\n.directive('progress', ['$log', '$progressSuppressWarning', function($log, $progressSuppressWarning) {\n return {\n replace: true,\n transclude: true,\n controller: 'ProgressController',\n require: 'progress',\n scope: {\n max: '=?',\n title: '@?'\n },\n templateUrl: 'template/progressbar/progress.html',\n link: function() {\n if (!$progressSuppressWarning) {\n $log.warn('progress is now deprecated. Use uib-progress instead.');\n }\n }\n };\n}])\n\n.directive('bar', ['$log', '$progressSuppressWarning', function($log, $progressSuppressWarning) {\n return {\n replace: true,\n transclude: true,\n require: '^progress',\n scope: {\n value: '=',\n type: '@'\n },\n templateUrl: 'template/progressbar/bar.html',\n link: function(scope, element, attrs, progressCtrl) {\n if (!$progressSuppressWarning) {\n $log.warn('bar is now deprecated. Use uib-bar instead.');\n }\n progressCtrl.addBar(scope, element);\n }\n };\n}])\n\n.directive('progressbar', ['$log', '$progressSuppressWarning', function($log, $progressSuppressWarning) {\n return {\n replace: true,\n transclude: true,\n controller: 'ProgressController',\n scope: {\n value: '=',\n max: '=?',\n type: '@'\n },\n templateUrl: 'template/progressbar/progressbar.html',\n link: function(scope, element, attrs, progressCtrl) {\n if (!$progressSuppressWarning) {\n $log.warn('progressbar is now deprecated. Use uib-progressbar instead.');\n }\n progressCtrl.addBar(scope, angular.element(element.children()[0]), {title: attrs.title});\n }\n };\n}]);\n\nangular.module('ui.bootstrap.rating', [])\n\n.constant('uibRatingConfig', {\n max: 5,\n stateOn: null,\n stateOff: null,\n titles : ['one', 'two', 'three', 'four', 'five']\n})\n\n.controller('UibRatingController', ['$scope', '$attrs', 'uibRatingConfig', function($scope, $attrs, ratingConfig) {\n var ngModelCtrl = { $setViewValue: angular.noop };\n\n this.init = function(ngModelCtrl_) {\n ngModelCtrl = ngModelCtrl_;\n ngModelCtrl.$render = this.render;\n\n ngModelCtrl.$formatters.push(function(value) {\n if (angular.isNumber(value) && value << 0 !== value) {\n value = Math.round(value);\n }\n return value;\n });\n\n this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn;\n this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff;\n var tmpTitles = angular.isDefined($attrs.titles) ? $scope.$parent.$eval($attrs.titles) : ratingConfig.titles ;\n this.titles = angular.isArray(tmpTitles) && tmpTitles.length > 0 ?\n tmpTitles : ratingConfig.titles;\n\n var ratingStates = angular.isDefined($attrs.ratingStates) ?\n $scope.$parent.$eval($attrs.ratingStates) :\n new Array(angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max);\n $scope.range = this.buildTemplateObjects(ratingStates);\n };\n\n this.buildTemplateObjects = function(states) {\n for (var i = 0, n = states.length; i < n; i++) {\n states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff, title: this.getTitle(i) }, states[i]);\n }\n return states;\n };\n\n this.getTitle = function(index) {\n if (index >= this.titles.length) {\n return index + 1;\n } else {\n return this.titles[index];\n }\n };\n\n $scope.rate = function(value) {\n if (!$scope.readonly && value >= 0 && value <= $scope.range.length) {\n ngModelCtrl.$setViewValue(ngModelCtrl.$viewValue === value ? 0 : value);\n ngModelCtrl.$render();\n }\n };\n\n $scope.enter = function(value) {\n if (!$scope.readonly) {\n $scope.value = value;\n }\n $scope.onHover({value: value});\n };\n\n $scope.reset = function() {\n $scope.value = ngModelCtrl.$viewValue;\n $scope.onLeave();\n };\n\n $scope.onKeydown = function(evt) {\n if (/(37|38|39|40)/.test(evt.which)) {\n evt.preventDefault();\n evt.stopPropagation();\n $scope.rate($scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1));\n }\n };\n\n this.render = function() {\n $scope.value = ngModelCtrl.$viewValue;\n };\n}])\n\n.directive('uibRating', function() {\n return {\n require: ['uibRating', 'ngModel'],\n scope: {\n readonly: '=?',\n onHover: '&',\n onLeave: '&'\n },\n controller: 'UibRatingController',\n templateUrl: 'template/rating/rating.html',\n replace: true,\n link: function(scope, element, attrs, ctrls) {\n var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n ratingCtrl.init(ngModelCtrl);\n }\n };\n});\n\n/* Deprecated rating below */\n\nangular.module('ui.bootstrap.rating')\n\n.value('$ratingSuppressWarning', false)\n\n.controller('RatingController', ['$scope', '$attrs', '$controller', '$log', '$ratingSuppressWarning', function($scope, $attrs, $controller, $log, $ratingSuppressWarning) {\n if (!$ratingSuppressWarning) {\n $log.warn('RatingController is now deprecated. Use UibRatingController instead.');\n }\n\n angular.extend(this, $controller('UibRatingController', {\n $scope: $scope,\n $attrs: $attrs\n }));\n}])\n\n.directive('rating', ['$log', '$ratingSuppressWarning', function($log, $ratingSuppressWarning) {\n return {\n require: ['rating', 'ngModel'],\n scope: {\n readonly: '=?',\n onHover: '&',\n onLeave: '&'\n },\n controller: 'RatingController',\n templateUrl: 'template/rating/rating.html',\n replace: true,\n link: function(scope, element, attrs, ctrls) {\n if (!$ratingSuppressWarning) {\n $log.warn('rating is now deprecated. Use uib-rating instead.');\n }\n var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n ratingCtrl.init(ngModelCtrl);\n }\n };\n}]);\n\n\n/**\n * @ngdoc overview\n * @name ui.bootstrap.tabs\n *\n * @description\n * AngularJS version of the tabs directive.\n */\n\nangular.module('ui.bootstrap.tabs', [])\n\n.controller('UibTabsetController', ['$scope', function ($scope) {\n var ctrl = this,\n tabs = ctrl.tabs = $scope.tabs = [];\n\n ctrl.select = function(selectedTab) {\n angular.forEach(tabs, function(tab) {\n if (tab.active && tab !== selectedTab) {\n tab.active = false;\n tab.onDeselect();\n selectedTab.selectCalled = false;\n }\n });\n selectedTab.active = true;\n // only call select if it has not already been called\n if (!selectedTab.selectCalled) {\n selectedTab.onSelect();\n selectedTab.selectCalled = true;\n }\n };\n\n ctrl.addTab = function addTab(tab) {\n tabs.push(tab);\n // we can't run the select function on the first tab\n // since that would select it twice\n if (tabs.length === 1 && tab.active !== false) {\n tab.active = true;\n } else if (tab.active) {\n ctrl.select(tab);\n } else {\n tab.active = false;\n }\n };\n\n ctrl.removeTab = function removeTab(tab) {\n var index = tabs.indexOf(tab);\n //Select a new tab if the tab to be removed is selected and not destroyed\n if (tab.active && tabs.length > 1 && !destroyed) {\n //If this is the last tab, select the previous tab. else, the next tab.\n var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1;\n ctrl.select(tabs[newActiveIndex]);\n }\n tabs.splice(index, 1);\n };\n\n var destroyed;\n $scope.$on('$destroy', function() {\n destroyed = true;\n });\n}])\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.tabs.directive:tabset\n * @restrict EA\n *\n * @description\n * Tabset is the outer container for the tabs directive\n *\n * @param {boolean=} vertical Whether or not to use vertical styling for the tabs.\n * @param {boolean=} justified Whether or not to use justified styling for the tabs.\n *\n * @example\n\n \n \n First Content!\n Second Content!\n \n
\n \n First Vertical Content!\n Second Vertical Content!\n \n \n First Justified Content!\n Second Justified Content!\n \n \n\n */\n.directive('uibTabset', function() {\n return {\n restrict: 'EA',\n transclude: true,\n replace: true,\n scope: {\n type: '@'\n },\n controller: 'UibTabsetController',\n templateUrl: 'template/tabs/tabset.html',\n link: function(scope, element, attrs) {\n scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false;\n scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false;\n }\n };\n})\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.tabs.directive:tab\n * @restrict EA\n *\n * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}.\n * @param {string=} select An expression to evaluate when the tab is selected.\n * @param {boolean=} active A binding, telling whether or not this tab is selected.\n * @param {boolean=} disabled A binding, telling whether or not this tab is disabled.\n *\n * @description\n * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}.\n *\n * @example\n\n \n \n \n \n
\n \n First Tab\n \n Alert me!\n Second Tab, with alert callback and html heading!\n \n \n {{item.content}}\n \n \n
\n \n \n function TabsDemoCtrl($scope) {\n $scope.items = [\n { title:\"Dynamic Title 1\", content:\"Dynamic Item 0\" },\n { title:\"Dynamic Title 2\", content:\"Dynamic Item 1\", disabled: true }\n ];\n\n $scope.alertMe = function() {\n setTimeout(function() {\n alert(\"You've selected the alert tab!\");\n });\n };\n };\n \n\n */\n\n/**\n * @ngdoc directive\n * @name ui.bootstrap.tabs.directive:tabHeading\n * @restrict EA\n *\n * @description\n * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element.\n *\n * @example\n\n \n \n \n HTML in my titles?!\n And some content, too!\n \n \n Icon heading?!?\n That's right.\n \n \n \n\n */\n.directive('uibTab', ['$parse', function($parse) {\n return {\n require: '^uibTabset',\n restrict: 'EA',\n replace: true,\n templateUrl: 'template/tabs/tab.html',\n transclude: true,\n scope: {\n active: '=?',\n heading: '@',\n onSelect: '&select', //This callback is called in contentHeadingTransclude\n //once it inserts the tab's content into the dom\n onDeselect: '&deselect'\n },\n controller: function() {\n //Empty controller so other directives can require being 'under' a tab\n },\n link: function(scope, elm, attrs, tabsetCtrl, transclude) {\n scope.$watch('active', function(active) {\n if (active) {\n tabsetCtrl.select(scope);\n }\n });\n\n scope.disabled = false;\n if (attrs.disable) {\n scope.$parent.$watch($parse(attrs.disable), function(value) {\n scope.disabled = !! value;\n });\n }\n\n scope.select = function() {\n if (!scope.disabled) {\n scope.active = true;\n }\n };\n\n tabsetCtrl.addTab(scope);\n scope.$on('$destroy', function() {\n tabsetCtrl.removeTab(scope);\n });\n\n //We need to transclude later, once the content container is ready.\n //when this link happens, we're inside a tab heading.\n scope.$transcludeFn = transclude;\n }\n };\n}])\n\n.directive('uibTabHeadingTransclude', function() {\n return {\n restrict: 'A',\n require: ['?^uibTab', '?^tab'], // TODO: change to '^uibTab' after deprecation removal\n link: function(scope, elm) {\n scope.$watch('headingElement', function updateHeadingElement(heading) {\n if (heading) {\n elm.html('');\n elm.append(heading);\n }\n });\n }\n };\n})\n\n.directive('uibTabContentTransclude', function() {\n return {\n restrict: 'A',\n require: ['?^uibTabset', '?^tabset'], // TODO: change to '^uibTabset' after deprecation removal\n link: function(scope, elm, attrs) {\n var tab = scope.$eval(attrs.uibTabContentTransclude);\n\n //Now our tab is ready to be transcluded: both the tab heading area\n //and the tab content area are loaded. Transclude 'em both.\n tab.$transcludeFn(tab.$parent, function(contents) {\n angular.forEach(contents, function(node) {\n if (isTabHeading(node)) {\n //Let tabHeadingTransclude know.\n tab.headingElement = node;\n } else {\n elm.append(node);\n }\n });\n });\n }\n };\n\n function isTabHeading(node) {\n return node.tagName && (\n node.hasAttribute('tab-heading') || // TODO: remove after deprecation removal\n node.hasAttribute('data-tab-heading') || // TODO: remove after deprecation removal\n node.hasAttribute('x-tab-heading') || // TODO: remove after deprecation removal\n node.hasAttribute('uib-tab-heading') ||\n node.hasAttribute('data-uib-tab-heading') ||\n node.hasAttribute('x-uib-tab-heading') ||\n node.tagName.toLowerCase() === 'tab-heading' || // TODO: remove after deprecation removal\n node.tagName.toLowerCase() === 'data-tab-heading' || // TODO: remove after deprecation removal\n node.tagName.toLowerCase() === 'x-tab-heading' || // TODO: remove after deprecation removal\n node.tagName.toLowerCase() === 'uib-tab-heading' ||\n node.tagName.toLowerCase() === 'data-uib-tab-heading' ||\n node.tagName.toLowerCase() === 'x-uib-tab-heading'\n );\n }\n});\n\n/* deprecated tabs below */\n\nangular.module('ui.bootstrap.tabs')\n\n .value('$tabsSuppressWarning', false)\n\n .controller('TabsetController', ['$scope', '$controller', '$log', '$tabsSuppressWarning', function($scope, $controller, $log, $tabsSuppressWarning) {\n if (!$tabsSuppressWarning) {\n $log.warn('TabsetController is now deprecated. Use UibTabsetController instead.');\n }\n\n angular.extend(this, $controller('UibTabsetController', {\n $scope: $scope\n }));\n }])\n\n .directive('tabset', ['$log', '$tabsSuppressWarning', function($log, $tabsSuppressWarning) {\n return {\n restrict: 'EA',\n transclude: true,\n replace: true,\n scope: {\n type: '@'\n },\n controller: 'TabsetController',\n templateUrl: 'template/tabs/tabset.html',\n link: function(scope, element, attrs) {\n\n if (!$tabsSuppressWarning) {\n $log.warn('tabset is now deprecated. Use uib-tabset instead.');\n }\n scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false;\n scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false;\n }\n };\n }])\n\n .directive('tab', ['$parse', '$log', '$tabsSuppressWarning', function($parse, $log, $tabsSuppressWarning) {\n return {\n require: '^tabset',\n restrict: 'EA',\n replace: true,\n templateUrl: 'template/tabs/tab.html',\n transclude: true,\n scope: {\n active: '=?',\n heading: '@',\n onSelect: '&select', //This callback is called in contentHeadingTransclude\n //once it inserts the tab's content into the dom\n onDeselect: '&deselect'\n },\n controller: function() {\n //Empty controller so other directives can require being 'under' a tab\n },\n link: function(scope, elm, attrs, tabsetCtrl, transclude) {\n if (!$tabsSuppressWarning) {\n $log.warn('tab is now deprecated. Use uib-tab instead.');\n }\n\n scope.$watch('active', function(active) {\n if (active) {\n tabsetCtrl.select(scope);\n }\n });\n\n scope.disabled = false;\n if (attrs.disable) {\n scope.$parent.$watch($parse(attrs.disable), function(value) {\n scope.disabled = !!value;\n });\n }\n\n scope.select = function() {\n if (!scope.disabled) {\n scope.active = true;\n }\n };\n\n tabsetCtrl.addTab(scope);\n scope.$on('$destroy', function() {\n tabsetCtrl.removeTab(scope);\n });\n\n //We need to transclude later, once the content container is ready.\n //when this link happens, we're inside a tab heading.\n scope.$transcludeFn = transclude;\n }\n };\n }])\n\n .directive('tabHeadingTransclude', ['$log', '$tabsSuppressWarning', function($log, $tabsSuppressWarning) {\n return {\n restrict: 'A',\n require: '^tab',\n link: function(scope, elm) {\n if (!$tabsSuppressWarning) {\n $log.warn('tab-heading-transclude is now deprecated. Use uib-tab-heading-transclude instead.');\n }\n\n scope.$watch('headingElement', function updateHeadingElement(heading) {\n if (heading) {\n elm.html('');\n elm.append(heading);\n }\n });\n }\n };\n }])\n\n .directive('tabContentTransclude', ['$log', '$tabsSuppressWarning', function($log, $tabsSuppressWarning) {\n return {\n restrict: 'A',\n require: '^tabset',\n link: function(scope, elm, attrs) {\n if (!$tabsSuppressWarning) {\n $log.warn('tab-content-transclude is now deprecated. Use uib-tab-content-transclude instead.');\n }\n\n var tab = scope.$eval(attrs.tabContentTransclude);\n\n //Now our tab is ready to be transcluded: both the tab heading area\n //and the tab content area are loaded. Transclude 'em both.\n tab.$transcludeFn(tab.$parent, function(contents) {\n angular.forEach(contents, function(node) {\n if (isTabHeading(node)) {\n //Let tabHeadingTransclude know.\n tab.headingElement = node;\n }\n else {\n elm.append(node);\n }\n });\n });\n }\n };\n\n function isTabHeading(node) {\n return node.tagName && (\n node.hasAttribute('tab-heading') ||\n node.hasAttribute('data-tab-heading') ||\n node.hasAttribute('x-tab-heading') ||\n node.tagName.toLowerCase() === 'tab-heading' ||\n node.tagName.toLowerCase() === 'data-tab-heading' ||\n node.tagName.toLowerCase() === 'x-tab-heading'\n );\n }\n }]);\n\nangular.module('ui.bootstrap.timepicker', [])\n\n.constant('uibTimepickerConfig', {\n hourStep: 1,\n minuteStep: 1,\n showMeridian: true,\n meridians: null,\n readonlyInput: false,\n mousewheel: true,\n arrowkeys: true,\n showSpinners: true\n})\n\n.controller('UibTimepickerController', ['$scope', '$element', '$attrs', '$parse', '$log', '$locale', 'uibTimepickerConfig', function($scope, $element, $attrs, $parse, $log, $locale, timepickerConfig) {\n var selected = new Date(),\n ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl\n meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS;\n\n $scope.tabindex = angular.isDefined($attrs.tabindex) ? $attrs.tabindex : 0;\n $element.removeAttr('tabindex');\n\n this.init = function(ngModelCtrl_, inputs) {\n ngModelCtrl = ngModelCtrl_;\n ngModelCtrl.$render = this.render;\n\n ngModelCtrl.$formatters.unshift(function(modelValue) {\n return modelValue ? new Date(modelValue) : null;\n });\n\n var hoursInputEl = inputs.eq(0),\n minutesInputEl = inputs.eq(1);\n\n var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel;\n if (mousewheel) {\n this.setupMousewheelEvents(hoursInputEl, minutesInputEl);\n }\n\n var arrowkeys = angular.isDefined($attrs.arrowkeys) ? $scope.$parent.$eval($attrs.arrowkeys) : timepickerConfig.arrowkeys;\n if (arrowkeys) {\n this.setupArrowkeyEvents(hoursInputEl, minutesInputEl);\n }\n\n $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput;\n this.setupInputEvents(hoursInputEl, minutesInputEl);\n };\n\n var hourStep = timepickerConfig.hourStep;\n if ($attrs.hourStep) {\n $scope.$parent.$watch($parse($attrs.hourStep), function(value) {\n hourStep = parseInt(value, 10);\n });\n }\n\n var minuteStep = timepickerConfig.minuteStep;\n if ($attrs.minuteStep) {\n $scope.$parent.$watch($parse($attrs.minuteStep), function(value) {\n minuteStep = parseInt(value, 10);\n });\n }\n\n var min;\n $scope.$parent.$watch($parse($attrs.min), function(value) {\n var dt = new Date(value);\n min = isNaN(dt) ? undefined : dt;\n });\n\n var max;\n $scope.$parent.$watch($parse($attrs.max), function(value) {\n var dt = new Date(value);\n max = isNaN(dt) ? undefined : dt;\n });\n\n $scope.noIncrementHours = function() {\n var incrementedSelected = addMinutes(selected, hourStep * 60);\n return incrementedSelected > max ||\n (incrementedSelected < selected && incrementedSelected < min);\n };\n\n $scope.noDecrementHours = function() {\n var decrementedSelected = addMinutes(selected, -hourStep * 60);\n return decrementedSelected < min ||\n (decrementedSelected > selected && decrementedSelected > max);\n };\n\n $scope.noIncrementMinutes = function() {\n var incrementedSelected = addMinutes(selected, minuteStep);\n return incrementedSelected > max ||\n (incrementedSelected < selected && incrementedSelected < min);\n };\n\n $scope.noDecrementMinutes = function() {\n var decrementedSelected = addMinutes(selected, -minuteStep);\n return decrementedSelected < min ||\n (decrementedSelected > selected && decrementedSelected > max);\n };\n\n $scope.noToggleMeridian = function() {\n if (selected.getHours() < 13) {\n return addMinutes(selected, 12 * 60) > max;\n } else {\n return addMinutes(selected, -12 * 60) < min;\n }\n };\n\n // 12H / 24H mode\n $scope.showMeridian = timepickerConfig.showMeridian;\n if ($attrs.showMeridian) {\n $scope.$parent.$watch($parse($attrs.showMeridian), function(value) {\n $scope.showMeridian = !!value;\n\n if (ngModelCtrl.$error.time) {\n // Evaluate from template\n var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate();\n if (angular.isDefined(hours) && angular.isDefined(minutes)) {\n selected.setHours(hours);\n refresh();\n }\n } else {\n updateTemplate();\n }\n });\n }\n\n // Get $scope.hours in 24H mode if valid\n function getHoursFromTemplate() {\n var hours = parseInt($scope.hours, 10);\n var valid = $scope.showMeridian ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24);\n if (!valid) {\n return undefined;\n }\n\n if ($scope.showMeridian) {\n if (hours === 12) {\n hours = 0;\n }\n if ($scope.meridian === meridians[1]) {\n hours = hours + 12;\n }\n }\n return hours;\n }\n\n function getMinutesFromTemplate() {\n var minutes = parseInt($scope.minutes, 10);\n return (minutes >= 0 && minutes < 60) ? minutes : undefined;\n }\n\n function pad(value) {\n return (angular.isDefined(value) && value.toString().length < 2) ? '0' + value : value.toString();\n }\n\n // Respond on mousewheel spin\n this.setupMousewheelEvents = function(hoursInputEl, minutesInputEl) {\n var isScrollingUp = function(e) {\n if (e.originalEvent) {\n e = e.originalEvent;\n }\n //pick correct delta variable depending on event\n var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY;\n return (e.detail || delta > 0);\n };\n\n hoursInputEl.bind('mousewheel wheel', function(e) {\n $scope.$apply(isScrollingUp(e) ? $scope.incrementHours() : $scope.decrementHours());\n e.preventDefault();\n });\n\n minutesInputEl.bind('mousewheel wheel', function(e) {\n $scope.$apply(isScrollingUp(e) ? $scope.incrementMinutes() : $scope.decrementMinutes());\n e.preventDefault();\n });\n\n };\n\n // Respond on up/down arrowkeys\n this.setupArrowkeyEvents = function(hoursInputEl, minutesInputEl) {\n hoursInputEl.bind('keydown', function(e) {\n if (e.which === 38) { // up\n e.preventDefault();\n $scope.incrementHours();\n $scope.$apply();\n } else if (e.which === 40) { // down\n e.preventDefault();\n $scope.decrementHours();\n $scope.$apply();\n }\n });\n\n minutesInputEl.bind('keydown', function(e) {\n if (e.which === 38) { // up\n e.preventDefault();\n $scope.incrementMinutes();\n $scope.$apply();\n } else if (e.which === 40) { // down\n e.preventDefault();\n $scope.decrementMinutes();\n $scope.$apply();\n }\n });\n };\n\n this.setupInputEvents = function(hoursInputEl, minutesInputEl) {\n if ($scope.readonlyInput) {\n $scope.updateHours = angular.noop;\n $scope.updateMinutes = angular.noop;\n return;\n }\n\n var invalidate = function(invalidHours, invalidMinutes) {\n ngModelCtrl.$setViewValue(null);\n ngModelCtrl.$setValidity('time', false);\n if (angular.isDefined(invalidHours)) {\n $scope.invalidHours = invalidHours;\n }\n if (angular.isDefined(invalidMinutes)) {\n $scope.invalidMinutes = invalidMinutes;\n }\n };\n\n $scope.updateHours = function() {\n var hours = getHoursFromTemplate(),\n minutes = getMinutesFromTemplate();\n\n if (angular.isDefined(hours) && angular.isDefined(minutes)) {\n selected.setHours(hours);\n if (selected < min || selected > max) {\n invalidate(true);\n } else {\n refresh('h');\n }\n } else {\n invalidate(true);\n }\n };\n\n hoursInputEl.bind('blur', function(e) {\n if (!$scope.invalidHours && $scope.hours < 10) {\n $scope.$apply(function() {\n $scope.hours = pad($scope.hours);\n });\n }\n });\n\n $scope.updateMinutes = function() {\n var minutes = getMinutesFromTemplate(),\n hours = getHoursFromTemplate();\n\n if (angular.isDefined(minutes) && angular.isDefined(hours)) {\n selected.setMinutes(minutes);\n if (selected < min || selected > max) {\n invalidate(undefined, true);\n } else {\n refresh('m');\n }\n } else {\n invalidate(undefined, true);\n }\n };\n\n minutesInputEl.bind('blur', function(e) {\n if (!$scope.invalidMinutes && $scope.minutes < 10) {\n $scope.$apply(function() {\n $scope.minutes = pad($scope.minutes);\n });\n }\n });\n\n };\n\n this.render = function() {\n var date = ngModelCtrl.$viewValue;\n\n if (isNaN(date)) {\n ngModelCtrl.$setValidity('time', false);\n $log.error('Timepicker directive: \"ng-model\" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');\n } else {\n if (date) {\n selected = date;\n }\n\n if (selected < min || selected > max) {\n ngModelCtrl.$setValidity('time', false);\n $scope.invalidHours = true;\n $scope.invalidMinutes = true;\n } else {\n makeValid();\n }\n updateTemplate();\n }\n };\n\n // Call internally when we know that model is valid.\n function refresh(keyboardChange) {\n makeValid();\n ngModelCtrl.$setViewValue(new Date(selected));\n updateTemplate(keyboardChange);\n }\n\n function makeValid() {\n ngModelCtrl.$setValidity('time', true);\n $scope.invalidHours = false;\n $scope.invalidMinutes = false;\n }\n\n function updateTemplate(keyboardChange) {\n var hours = selected.getHours(), minutes = selected.getMinutes();\n\n if ($scope.showMeridian) {\n hours = (hours === 0 || hours === 12) ? 12 : hours % 12; // Convert 24 to 12 hour system\n }\n\n $scope.hours = keyboardChange === 'h' ? hours : pad(hours);\n if (keyboardChange !== 'm') {\n $scope.minutes = pad(minutes);\n }\n $scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1];\n }\n\n function addMinutes(date, minutes) {\n var dt = new Date(date.getTime() + minutes * 60000);\n var newDate = new Date(date);\n newDate.setHours(dt.getHours(), dt.getMinutes());\n return newDate;\n }\n\n function addMinutesToSelected(minutes) {\n selected = addMinutes(selected, minutes);\n refresh();\n }\n\n $scope.showSpinners = angular.isDefined($attrs.showSpinners) ?\n $scope.$parent.$eval($attrs.showSpinners) : timepickerConfig.showSpinners;\n\n $scope.incrementHours = function() {\n if (!$scope.noIncrementHours()) {\n addMinutesToSelected(hourStep * 60);\n }\n };\n\n $scope.decrementHours = function() {\n if (!$scope.noDecrementHours()) {\n addMinutesToSelected(-hourStep * 60);\n }\n };\n\n $scope.incrementMinutes = function() {\n if (!$scope.noIncrementMinutes()) {\n addMinutesToSelected(minuteStep);\n }\n };\n\n $scope.decrementMinutes = function() {\n if (!$scope.noDecrementMinutes()) {\n addMinutesToSelected(-minuteStep);\n }\n };\n\n $scope.toggleMeridian = function() {\n if (!$scope.noToggleMeridian()) {\n addMinutesToSelected(12 * 60 * (selected.getHours() < 12 ? 1 : -1));\n }\n };\n}])\n\n.directive('uibTimepicker', function() {\n return {\n restrict: 'EA',\n require: ['uibTimepicker', '?^ngModel'],\n controller: 'UibTimepickerController',\n controllerAs: 'timepicker',\n replace: true,\n scope: {},\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/timepicker/timepicker.html';\n },\n link: function(scope, element, attrs, ctrls) {\n var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n if (ngModelCtrl) {\n timepickerCtrl.init(ngModelCtrl, element.find('input'));\n }\n }\n };\n});\n\n/* Deprecated timepicker below */\n\nangular.module('ui.bootstrap.timepicker')\n\n.value('$timepickerSuppressWarning', false)\n\n.controller('TimepickerController', ['$scope', '$element', '$attrs', '$controller', '$log', '$timepickerSuppressWarning', function($scope, $element, $attrs, $controller, $log, $timepickerSuppressWarning) {\n if (!$timepickerSuppressWarning) {\n $log.warn('TimepickerController is now deprecated. Use UibTimepickerController instead.');\n }\n\n angular.extend(this, $controller('UibTimepickerController', {\n $scope: $scope,\n $element: $element,\n $attrs: $attrs\n }));\n}])\n\n.directive('timepicker', ['$log', '$timepickerSuppressWarning', function($log, $timepickerSuppressWarning) {\n return {\n restrict: 'EA',\n require: ['timepicker', '?^ngModel'],\n controller: 'TimepickerController',\n controllerAs: 'timepicker',\n replace: true,\n scope: {},\n templateUrl: function(element, attrs) {\n return attrs.templateUrl || 'template/timepicker/timepicker.html';\n },\n link: function(scope, element, attrs, ctrls) {\n if (!$timepickerSuppressWarning) {\n $log.warn('timepicker is now deprecated. Use uib-timepicker instead.');\n }\n var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];\n\n if (ngModelCtrl) {\n timepickerCtrl.init(ngModelCtrl, element.find('input'));\n }\n }\n };\n}]);\n\nangular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])\n\n/**\n * A helper service that can parse typeahead's syntax (string provided by users)\n * Extracted to a separate service for ease of unit testing\n */\n .factory('uibTypeaheadParser', ['$parse', function($parse) {\n // 00000111000000000000022200000000000000003333333333333330000000000044000\n var TYPEAHEAD_REGEXP = /^\\s*([\\s\\S]+?)(?:\\s+as\\s+([\\s\\S]+?))?\\s+for\\s+(?:([\\$\\w][\\$\\w\\d]*))\\s+in\\s+([\\s\\S]+?)$/;\n return {\n parse: function(input) {\n var match = input.match(TYPEAHEAD_REGEXP);\n if (!match) {\n throw new Error(\n 'Expected typeahead specification in form of \"_modelValue_ (as _label_)? for _item_ in _collection_\"' +\n ' but got \"' + input + '\".');\n }\n\n return {\n itemName: match[3],\n source: $parse(match[4]),\n viewMapper: $parse(match[2] || match[1]),\n modelMapper: $parse(match[1])\n };\n }\n };\n }])\n\n .controller('UibTypeaheadController', ['$scope', '$element', '$attrs', '$compile', '$parse', '$q', '$timeout', '$document', '$window', '$rootScope', '$uibPosition', 'uibTypeaheadParser',\n function(originalScope, element, attrs, $compile, $parse, $q, $timeout, $document, $window, $rootScope, $position, typeaheadParser) {\n var HOT_KEYS = [9, 13, 27, 38, 40];\n var eventDebounceTime = 200;\n var modelCtrl, ngModelOptions;\n //SUPPORTED ATTRIBUTES (OPTIONS)\n\n //minimal no of characters that needs to be entered before typeahead kicks-in\n var minLength = originalScope.$eval(attrs.typeaheadMinLength);\n if (!minLength && minLength !== 0) {\n minLength = 1;\n }\n\n //minimal wait time after last character typed before typeahead kicks-in\n var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;\n\n //should it restrict model values to the ones selected from the popup only?\n var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;\n\n //binding to a variable that indicates if matches are being retrieved asynchronously\n var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;\n\n //a callback executed when a match is selected\n var onSelectCallback = $parse(attrs.typeaheadOnSelect);\n\n //should it select highlighted popup value when losing focus?\n var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false;\n\n //binding to a variable that indicates if there were no results after the query is completed\n var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop;\n\n var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;\n\n var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;\n\n var appendToElementId = attrs.typeaheadAppendToElementId || false;\n\n var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;\n\n //If input matches an item of the list exactly, select it automatically\n var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false;\n\n //INTERNAL VARIABLES\n\n //model setter executed upon match selection\n var parsedModel = $parse(attrs.ngModel);\n var invokeModelSetter = $parse(attrs.ngModel + '($$$p)');\n var $setModelValue = function(scope, newValue) {\n if (angular.isFunction(parsedModel(originalScope)) &&\n ngModelOptions && ngModelOptions.$options && ngModelOptions.$options.getterSetter) {\n return invokeModelSetter(scope, {$$$p: newValue});\n } else {\n return parsedModel.assign(scope, newValue);\n }\n };\n\n //expressions used by typeahead\n var parserResult = typeaheadParser.parse(attrs.uibTypeahead);\n\n var hasFocus;\n\n //Used to avoid bug in iOS webview where iOS keyboard does not fire\n //mousedown & mouseup events\n //Issue #3699\n var selected;\n\n //create a child scope for the typeahead directive so we are not polluting original scope\n //with typeahead-specific data (matches, query etc.)\n var scope = originalScope.$new();\n var offDestroy = originalScope.$on('$destroy', function() {\n scope.$destroy();\n });\n scope.$on('$destroy', offDestroy);\n\n // WAI-ARIA\n var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000);\n element.attr({\n 'aria-autocomplete': 'list',\n 'aria-expanded': false,\n 'aria-owns': popupId\n });\n\n //pop-up element used to display matches\n var popUpEl = angular.element('');\n popUpEl.attr({\n id: popupId,\n matches: 'matches',\n active: 'activeIdx',\n select: 'select(activeIdx)',\n 'move-in-progress': 'moveInProgress',\n query: 'query',\n position: 'position'\n });\n //custom item template\n if (angular.isDefined(attrs.typeaheadTemplateUrl)) {\n popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);\n }\n\n if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) {\n popUpEl.attr('popup-template-url', attrs.typeaheadPopupTemplateUrl);\n }\n\n var resetMatches = function() {\n scope.matches = [];\n scope.activeIdx = -1;\n element.attr('aria-expanded', false);\n };\n\n var getMatchId = function(index) {\n return popupId + '-option-' + index;\n };\n\n // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead.\n // This attribute is added or removed automatically when the `activeIdx` changes.\n scope.$watch('activeIdx', function(index) {\n if (index < 0) {\n element.removeAttr('aria-activedescendant');\n } else {\n element.attr('aria-activedescendant', getMatchId(index));\n }\n });\n\n var inputIsExactMatch = function(inputValue, index) {\n if (scope.matches.length > index && inputValue) {\n return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase();\n }\n\n return false;\n };\n\n var getMatchesAsync = function(inputValue) {\n var locals = {$viewValue: inputValue};\n isLoadingSetter(originalScope, true);\n isNoResultsSetter(originalScope, false);\n $q.when(parserResult.source(originalScope, locals)).then(function(matches) {\n //it might happen that several async queries were in progress if a user were typing fast\n //but we are interested only in responses that correspond to the current view value\n var onCurrentRequest = (inputValue === modelCtrl.$viewValue);\n if (onCurrentRequest && hasFocus) {\n if (matches && matches.length > 0) {\n scope.activeIdx = focusFirst ? 0 : -1;\n isNoResultsSetter(originalScope, false);\n scope.matches.length = 0;\n\n //transform labels\n for (var i = 0; i < matches.length; i++) {\n locals[parserResult.itemName] = matches[i];\n scope.matches.push({\n id: getMatchId(i),\n label: parserResult.viewMapper(scope, locals),\n model: matches[i]\n });\n }\n\n scope.query = inputValue;\n //position pop-up with matches - we need to re-calculate its position each time we are opening a window\n //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page\n //due to other elements being rendered\n recalculatePosition();\n\n element.attr('aria-expanded', true);\n\n //Select the single remaining option if user input matches\n if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) {\n scope.select(0);\n }\n } else {\n resetMatches();\n isNoResultsSetter(originalScope, true);\n }\n }\n if (onCurrentRequest) {\n isLoadingSetter(originalScope, false);\n }\n }, function() {\n resetMatches();\n isLoadingSetter(originalScope, false);\n isNoResultsSetter(originalScope, true);\n });\n };\n\n // bind events only if appendToBody params exist - performance feature\n if (appendToBody) {\n angular.element($window).bind('resize', fireRecalculating);\n $document.find('body').bind('scroll', fireRecalculating);\n }\n\n // Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later\n var timeoutEventPromise;\n\n // Default progress type\n scope.moveInProgress = false;\n\n function fireRecalculating() {\n if (!scope.moveInProgress) {\n scope.moveInProgress = true;\n scope.$digest();\n }\n\n // Cancel previous timeout\n if (timeoutEventPromise) {\n $timeout.cancel(timeoutEventPromise);\n }\n\n // Debounced executing recalculate after events fired\n timeoutEventPromise = $timeout(function() {\n // if popup is visible\n if (scope.matches.length) {\n recalculatePosition();\n }\n\n scope.moveInProgress = false;\n }, eventDebounceTime);\n }\n\n // recalculate actual position and set new values to scope\n // after digest loop is popup in right position\n function recalculatePosition() {\n scope.position = appendToBody ? $position.offset(element) : $position.position(element);\n scope.position.top += element.prop('offsetHeight');\n }\n\n //we need to propagate user's query so we can higlight matches\n scope.query = undefined;\n\n //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later\n var timeoutPromise;\n\n var scheduleSearchWithTimeout = function(inputValue) {\n timeoutPromise = $timeout(function() {\n getMatchesAsync(inputValue);\n }, waitTime);\n };\n\n var cancelPreviousTimeout = function() {\n if (timeoutPromise) {\n $timeout.cancel(timeoutPromise);\n }\n };\n\n resetMatches();\n\n scope.select = function(activeIdx) {\n //called from within the $digest() cycle\n var locals = {};\n var model, item;\n\n selected = true;\n locals[parserResult.itemName] = item = scope.matches[activeIdx].model;\n model = parserResult.modelMapper(originalScope, locals);\n $setModelValue(originalScope, model);\n modelCtrl.$setValidity('editable', true);\n modelCtrl.$setValidity('parse', true);\n\n onSelectCallback(originalScope, {\n $item: item,\n $model: model,\n $label: parserResult.viewMapper(originalScope, locals)\n });\n\n resetMatches();\n\n //return focus to the input element if a match was selected via a mouse click event\n // use timeout to avoid $rootScope:inprog error\n if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) {\n $timeout(function() { element[0].focus(); }, 0, false);\n }\n };\n\n //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\n element.bind('keydown', function(evt) {\n //typeahead is open and an \"interesting\" key was pressed\n if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {\n return;\n }\n\n // if there's nothing selected (i.e. focusFirst) and enter or tab is hit, clear the results\n if (scope.activeIdx === -1 && (evt.which === 9 || evt.which === 13)) {\n resetMatches();\n scope.$digest();\n return;\n }\n\n evt.preventDefault();\n\n if (evt.which === 40) {\n scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;\n scope.$digest();\n } else if (evt.which === 38) {\n scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;\n scope.$digest();\n } else if (evt.which === 13 || evt.which === 9) {\n scope.$apply(function () {\n scope.select(scope.activeIdx);\n });\n } else if (evt.which === 27) {\n evt.stopPropagation();\n\n resetMatches();\n scope.$digest();\n }\n });\n\n element.bind('blur', function() {\n if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) {\n selected = true;\n scope.$apply(function() {\n scope.select(scope.activeIdx);\n });\n }\n hasFocus = false;\n selected = false;\n });\n\n // Keep reference to click handler to unbind it.\n var dismissClickHandler = function(evt) {\n // Issue #3973\n // Firefox treats right click as a click on document\n if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) {\n resetMatches();\n if (!$rootScope.$$phase) {\n scope.$digest();\n }\n }\n };\n\n $document.bind('click', dismissClickHandler);\n\n originalScope.$on('$destroy', function() {\n $document.unbind('click', dismissClickHandler);\n if (appendToBody || appendToElementId) {\n $popup.remove();\n }\n\n if (appendToBody) {\n angular.element($window).unbind('resize', fireRecalculating);\n $document.find('body').unbind('scroll', fireRecalculating);\n }\n // Prevent jQuery cache memory leak\n popUpEl.remove();\n });\n\n var $popup = $compile(popUpEl)(scope);\n\n if (appendToBody) {\n $document.find('body').append($popup);\n } else if (appendToElementId !== false) {\n angular.element($document[0].getElementById(appendToElementId)).append($popup);\n } else {\n element.after($popup);\n }\n\n this.init = function(_modelCtrl, _ngModelOptions) {\n modelCtrl = _modelCtrl;\n ngModelOptions = _ngModelOptions;\n\n //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM\n //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue\n modelCtrl.$parsers.unshift(function(inputValue) {\n hasFocus = true;\n\n if (minLength === 0 || inputValue && inputValue.length >= minLength) {\n if (waitTime > 0) {\n cancelPreviousTimeout();\n scheduleSearchWithTimeout(inputValue);\n } else {\n getMatchesAsync(inputValue);\n }\n } else {\n isLoadingSetter(originalScope, false);\n cancelPreviousTimeout();\n resetMatches();\n }\n\n if (isEditable) {\n return inputValue;\n } else {\n if (!inputValue) {\n // Reset in case user had typed something previously.\n modelCtrl.$setValidity('editable', true);\n return null;\n } else {\n modelCtrl.$setValidity('editable', false);\n return undefined;\n }\n }\n });\n\n modelCtrl.$formatters.push(function(modelValue) {\n var candidateViewValue, emptyViewValue;\n var locals = {};\n\n // The validity may be set to false via $parsers (see above) if\n // the model is restricted to selected values. If the model\n // is set manually it is considered to be valid.\n if (!isEditable) {\n modelCtrl.$setValidity('editable', true);\n }\n\n if (inputFormatter) {\n locals.$model = modelValue;\n return inputFormatter(originalScope, locals);\n } else {\n //it might happen that we don't have enough info to properly render input value\n //we need to check for this situation and simply return model value if we can't apply custom formatting\n locals[parserResult.itemName] = modelValue;\n candidateViewValue = parserResult.viewMapper(originalScope, locals);\n locals[parserResult.itemName] = undefined;\n emptyViewValue = parserResult.viewMapper(originalScope, locals);\n\n return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue;\n }\n });\n };\n }])\n\n .directive('uibTypeahead', function() {\n return {\n controller: 'UibTypeaheadController',\n require: ['ngModel', '^?ngModelOptions', 'uibTypeahead'],\n link: function(originalScope, element, attrs, ctrls) {\n ctrls[2].init(ctrls[0], ctrls[1]);\n }\n };\n })\n\n .directive('uibTypeaheadPopup', function() {\n return {\n scope: {\n matches: '=',\n query: '=',\n active: '=',\n position: '&',\n moveInProgress: '=',\n select: '&'\n },\n replace: true,\n templateUrl: function(element, attrs) {\n return attrs.popupTemplateUrl || 'template/typeahead/typeahead-popup.html';\n },\n link: function(scope, element, attrs) {\n scope.templateUrl = attrs.templateUrl;\n\n scope.isOpen = function() {\n return scope.matches.length > 0;\n };\n\n scope.isActive = function(matchIdx) {\n return scope.active == matchIdx;\n };\n\n scope.selectActive = function(matchIdx) {\n scope.active = matchIdx;\n };\n\n scope.selectMatch = function(activeIdx) {\n scope.select({activeIdx:activeIdx});\n };\n }\n };\n })\n\n .directive('uibTypeaheadMatch', ['$templateRequest', '$compile', '$parse', function($templateRequest, $compile, $parse) {\n return {\n scope: {\n index: '=',\n match: '=',\n query: '='\n },\n link:function(scope, element, attrs) {\n var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html';\n $templateRequest(tplUrl).then(function(tplContent) {\n $compile(tplContent.trim())(scope, function(clonedElement) {\n element.replaceWith(clonedElement);\n });\n });\n }\n };\n }])\n\n .filter('uibTypeaheadHighlight', ['$sce', '$injector', '$log', function($sce, $injector, $log) {\n var isSanitizePresent;\n isSanitizePresent = $injector.has('$sanitize');\n\n function escapeRegexp(queryToEscape) {\n // Regex: capture the whole query string and replace it with the string that will be used to match\n // the results, for example if the capture is \"a\" the result will be \\a\n return queryToEscape.replace(/([.?*+^$[\\]\\\\(){}|-])/g, '\\\\$1');\n }\n\n function containsHtml(matchItem) {\n return /<.*>/g.test(matchItem);\n }\n\n return function(matchItem, query) {\n if (!isSanitizePresent && containsHtml(matchItem)) {\n $log.warn('Unsafe use of typeahead please use ngSanitize'); // Warn the user about the danger\n }\n matchItem = query? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; // Replaces the capture string with a the same string inside of a \"strong\" tag\n if (!isSanitizePresent) {\n matchItem = $sce.trustAsHtml(matchItem); // If $sanitize is not present we pack the string in a $sce object for the ng-bind-html directive\n }\n return matchItem;\n };\n }]);\n\n/* Deprecated typeahead below */\n \nangular.module('ui.bootstrap.typeahead')\n .value('$typeaheadSuppressWarning', false)\n .service('typeaheadParser', ['$parse', 'uibTypeaheadParser', '$log', '$typeaheadSuppressWarning', function($parse, uibTypeaheadParser, $log, $typeaheadSuppressWarning) {\n if (!$typeaheadSuppressWarning) {\n $log.warn('typeaheadParser is now deprecated. Use uibTypeaheadParser instead.');\n }\n\n return uibTypeaheadParser;\n }])\n\n .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$window', '$rootScope', '$uibPosition', 'typeaheadParser', '$log', '$typeaheadSuppressWarning',\n function($compile, $parse, $q, $timeout, $document, $window, $rootScope, $position, typeaheadParser, $log, $typeaheadSuppressWarning) {\n var HOT_KEYS = [9, 13, 27, 38, 40];\n var eventDebounceTime = 200;\n return {\n require: ['ngModel', '^?ngModelOptions'],\n link: function(originalScope, element, attrs, ctrls) {\n if (!$typeaheadSuppressWarning) {\n $log.warn('typeahead is now deprecated. Use uib-typeahead instead.');\n }\n var modelCtrl = ctrls[0];\n var ngModelOptions = ctrls[1];\n //SUPPORTED ATTRIBUTES (OPTIONS)\n\n //minimal no of characters that needs to be entered before typeahead kicks-in\n var minLength = originalScope.$eval(attrs.typeaheadMinLength);\n if (!minLength && minLength !== 0) {\n minLength = 1;\n }\n\n //minimal wait time after last character typed before typeahead kicks-in\n var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;\n\n //should it restrict model values to the ones selected from the popup only?\n var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;\n\n //binding to a variable that indicates if matches are being retrieved asynchronously\n var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;\n\n //a callback executed when a match is selected\n var onSelectCallback = $parse(attrs.typeaheadOnSelect);\n\n //should it select highlighted popup value when losing focus?\n var isSelectOnBlur = angular.isDefined(attrs.typeaheadSelectOnBlur) ? originalScope.$eval(attrs.typeaheadSelectOnBlur) : false;\n\n //binding to a variable that indicates if there were no results after the query is completed\n var isNoResultsSetter = $parse(attrs.typeaheadNoResults).assign || angular.noop;\n\n var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;\n\n var appendToBody = attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;\n\n var appendToElementId = attrs.typeaheadAppendToElementId || false;\n\n var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;\n\n //If input matches an item of the list exactly, select it automatically\n var selectOnExact = attrs.typeaheadSelectOnExact ? originalScope.$eval(attrs.typeaheadSelectOnExact) : false;\n\n //INTERNAL VARIABLES\n\n //model setter executed upon match selection\n var parsedModel = $parse(attrs.ngModel);\n var invokeModelSetter = $parse(attrs.ngModel + '($$$p)');\n var $setModelValue = function(scope, newValue) {\n if (angular.isFunction(parsedModel(originalScope)) &&\n ngModelOptions && ngModelOptions.$options && ngModelOptions.$options.getterSetter) {\n return invokeModelSetter(scope, {$$$p: newValue});\n } else {\n return parsedModel.assign(scope, newValue);\n }\n };\n\n //expressions used by typeahead\n var parserResult = typeaheadParser.parse(attrs.typeahead);\n\n var hasFocus;\n\n //Used to avoid bug in iOS webview where iOS keyboard does not fire\n //mousedown & mouseup events\n //Issue #3699\n var selected;\n\n //create a child scope for the typeahead directive so we are not polluting original scope\n //with typeahead-specific data (matches, query etc.)\n var scope = originalScope.$new();\n var offDestroy = originalScope.$on('$destroy', function() {\n\t\t\t scope.$destroy();\n });\n scope.$on('$destroy', offDestroy);\n\n // WAI-ARIA\n var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000);\n element.attr({\n 'aria-autocomplete': 'list',\n 'aria-expanded': false,\n 'aria-owns': popupId\n });\n\n //pop-up element used to display matches\n var popUpEl = angular.element('');\n popUpEl.attr({\n id: popupId,\n matches: 'matches',\n active: 'activeIdx',\n select: 'select(activeIdx)',\n 'move-in-progress': 'moveInProgress',\n query: 'query',\n position: 'position'\n });\n //custom item template\n if (angular.isDefined(attrs.typeaheadTemplateUrl)) {\n popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);\n }\n\n if (angular.isDefined(attrs.typeaheadPopupTemplateUrl)) {\n popUpEl.attr('popup-template-url', attrs.typeaheadPopupTemplateUrl);\n }\n\n var resetMatches = function() {\n scope.matches = [];\n scope.activeIdx = -1;\n element.attr('aria-expanded', false);\n };\n\n var getMatchId = function(index) {\n return popupId + '-option-' + index;\n };\n\n // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead.\n // This attribute is added or removed automatically when the `activeIdx` changes.\n scope.$watch('activeIdx', function(index) {\n if (index < 0) {\n element.removeAttr('aria-activedescendant');\n } else {\n element.attr('aria-activedescendant', getMatchId(index));\n }\n });\n\n var inputIsExactMatch = function(inputValue, index) {\n if (scope.matches.length > index && inputValue) {\n return inputValue.toUpperCase() === scope.matches[index].label.toUpperCase();\n }\n\n return false;\n };\n\n var getMatchesAsync = function(inputValue) {\n var locals = {$viewValue: inputValue};\n isLoadingSetter(originalScope, true);\n isNoResultsSetter(originalScope, false);\n $q.when(parserResult.source(originalScope, locals)).then(function(matches) {\n //it might happen that several async queries were in progress if a user were typing fast\n //but we are interested only in responses that correspond to the current view value\n var onCurrentRequest = (inputValue === modelCtrl.$viewValue);\n if (onCurrentRequest && hasFocus) {\n if (matches && matches.length > 0) {\n scope.activeIdx = focusFirst ? 0 : -1;\n isNoResultsSetter(originalScope, false);\n scope.matches.length = 0;\n\n //transform labels\n for (var i = 0; i < matches.length; i++) {\n locals[parserResult.itemName] = matches[i];\n scope.matches.push({\n id: getMatchId(i),\n label: parserResult.viewMapper(scope, locals),\n model: matches[i]\n });\n }\n\n scope.query = inputValue;\n //position pop-up with matches - we need to re-calculate its position each time we are opening a window\n //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page\n //due to other elements being rendered\n recalculatePosition();\n\n element.attr('aria-expanded', true);\n\n //Select the single remaining option if user input matches\n if (selectOnExact && scope.matches.length === 1 && inputIsExactMatch(inputValue, 0)) {\n scope.select(0);\n }\n } else {\n resetMatches();\n isNoResultsSetter(originalScope, true);\n }\n }\n if (onCurrentRequest) {\n isLoadingSetter(originalScope, false);\n }\n }, function() {\n resetMatches();\n isLoadingSetter(originalScope, false);\n isNoResultsSetter(originalScope, true);\n });\n };\n\n // bind events only if appendToBody params exist - performance feature\n if (appendToBody) {\n angular.element($window).bind('resize', fireRecalculating);\n $document.find('body').bind('scroll', fireRecalculating);\n }\n\n // Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later\n var timeoutEventPromise;\n\n // Default progress type\n scope.moveInProgress = false;\n\n function fireRecalculating() {\n if (!scope.moveInProgress) {\n scope.moveInProgress = true;\n scope.$digest();\n }\n\n // Cancel previous timeout\n if (timeoutEventPromise) {\n $timeout.cancel(timeoutEventPromise);\n }\n\n // Debounced executing recalculate after events fired\n timeoutEventPromise = $timeout(function() {\n // if popup is visible\n if (scope.matches.length) {\n recalculatePosition();\n }\n\n scope.moveInProgress = false;\n }, eventDebounceTime);\n }\n\n // recalculate actual position and set new values to scope\n // after digest loop is popup in right position\n function recalculatePosition() {\n scope.position = appendToBody ? $position.offset(element) : $position.position(element);\n scope.position.top += element.prop('offsetHeight');\n }\n\n resetMatches();\n\n //we need to propagate user's query so we can higlight matches\n scope.query = undefined;\n\n //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later\n var timeoutPromise;\n\n var scheduleSearchWithTimeout = function(inputValue) {\n timeoutPromise = $timeout(function() {\n getMatchesAsync(inputValue);\n }, waitTime);\n };\n\n var cancelPreviousTimeout = function() {\n if (timeoutPromise) {\n $timeout.cancel(timeoutPromise);\n }\n };\n\n //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM\n //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue\n modelCtrl.$parsers.unshift(function(inputValue) {\n hasFocus = true;\n\n if (minLength === 0 || inputValue && inputValue.length >= minLength) {\n if (waitTime > 0) {\n cancelPreviousTimeout();\n scheduleSearchWithTimeout(inputValue);\n } else {\n getMatchesAsync(inputValue);\n }\n } else {\n isLoadingSetter(originalScope, false);\n cancelPreviousTimeout();\n resetMatches();\n }\n\n if (isEditable) {\n return inputValue;\n } else {\n if (!inputValue) {\n // Reset in case user had typed something previously.\n modelCtrl.$setValidity('editable', true);\n return null;\n } else {\n modelCtrl.$setValidity('editable', false);\n return undefined;\n }\n }\n });\n\n modelCtrl.$formatters.push(function(modelValue) {\n var candidateViewValue, emptyViewValue;\n var locals = {};\n\n // The validity may be set to false via $parsers (see above) if\n // the model is restricted to selected values. If the model\n // is set manually it is considered to be valid.\n if (!isEditable) {\n modelCtrl.$setValidity('editable', true);\n }\n\n if (inputFormatter) {\n locals.$model = modelValue;\n return inputFormatter(originalScope, locals);\n } else {\n //it might happen that we don't have enough info to properly render input value\n //we need to check for this situation and simply return model value if we can't apply custom formatting\n locals[parserResult.itemName] = modelValue;\n candidateViewValue = parserResult.viewMapper(originalScope, locals);\n locals[parserResult.itemName] = undefined;\n emptyViewValue = parserResult.viewMapper(originalScope, locals);\n\n return candidateViewValue !== emptyViewValue ? candidateViewValue : modelValue;\n }\n });\n\n scope.select = function(activeIdx) {\n //called from within the $digest() cycle\n var locals = {};\n var model, item;\n\n selected = true;\n locals[parserResult.itemName] = item = scope.matches[activeIdx].model;\n model = parserResult.modelMapper(originalScope, locals);\n $setModelValue(originalScope, model);\n modelCtrl.$setValidity('editable', true);\n modelCtrl.$setValidity('parse', true);\n\n onSelectCallback(originalScope, {\n $item: item,\n $model: model,\n $label: parserResult.viewMapper(originalScope, locals)\n });\n\n resetMatches();\n\n //return focus to the input element if a match was selected via a mouse click event\n // use timeout to avoid $rootScope:inprog error\n if (scope.$eval(attrs.typeaheadFocusOnSelect) !== false) {\n $timeout(function() { element[0].focus(); }, 0, false);\n }\n };\n\n //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)\n element.bind('keydown', function(evt) {\n //typeahead is open and an \"interesting\" key was pressed\n if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {\n return;\n }\n\n // if there's nothing selected (i.e. focusFirst) and enter or tab is hit, clear the results\n if (scope.activeIdx === -1 && (evt.which === 9 || evt.which === 13)) {\n resetMatches();\n scope.$digest();\n return;\n }\n\n evt.preventDefault();\n\n if (evt.which === 40) {\n scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;\n scope.$digest();\n } else if (evt.which === 38) {\n scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;\n scope.$digest();\n } else if (evt.which === 13 || evt.which === 9) {\n scope.$apply(function () {\n scope.select(scope.activeIdx);\n });\n } else if (evt.which === 27) {\n evt.stopPropagation();\n\n resetMatches();\n scope.$digest();\n }\n });\n\n element.bind('blur', function() {\n if (isSelectOnBlur && scope.matches.length && scope.activeIdx !== -1 && !selected) {\n selected = true;\n scope.$apply(function() {\n scope.select(scope.activeIdx);\n });\n }\n hasFocus = false;\n selected = false;\n });\n\n // Keep reference to click handler to unbind it.\n var dismissClickHandler = function(evt) {\n // Issue #3973\n // Firefox treats right click as a click on document\n if (element[0] !== evt.target && evt.which !== 3 && scope.matches.length !== 0) {\n resetMatches();\n if (!$rootScope.$$phase) {\n scope.$digest();\n }\n }\n };\n\n $document.bind('click', dismissClickHandler);\n\n originalScope.$on('$destroy', function() {\n $document.unbind('click', dismissClickHandler);\n if (appendToBody || appendToElementId) {\n $popup.remove();\n }\n\n if (appendToBody) {\n angular.element($window).unbind('resize', fireRecalculating);\n $document.find('body').unbind('scroll', fireRecalculating);\n }\n // Prevent jQuery cache memory leak\n popUpEl.remove();\n });\n\n var $popup = $compile(popUpEl)(scope);\n\n if (appendToBody) {\n $document.find('body').append($popup);\n } else if (appendToElementId !== false) {\n angular.element($document[0].getElementById(appendToElementId)).append($popup);\n } else {\n element.after($popup);\n }\n }\n };\n }])\n \n .directive('typeaheadPopup', ['$typeaheadSuppressWarning', '$log', function($typeaheadSuppressWarning, $log) {\n return {\n scope: {\n matches: '=',\n query: '=',\n active: '=',\n position: '&',\n moveInProgress: '=',\n select: '&'\n },\n replace: true,\n templateUrl: function(element, attrs) {\n return attrs.popupTemplateUrl || 'template/typeahead/typeahead-popup.html';\n },\n link: function(scope, element, attrs) {\n \n if (!$typeaheadSuppressWarning) {\n $log.warn('typeahead-popup is now deprecated. Use uib-typeahead-popup instead.');\n }\n scope.templateUrl = attrs.templateUrl;\n\n scope.isOpen = function() {\n return scope.matches.length > 0;\n };\n\n scope.isActive = function(matchIdx) {\n return scope.active == matchIdx;\n };\n\n scope.selectActive = function(matchIdx) {\n scope.active = matchIdx;\n };\n\n scope.selectMatch = function(activeIdx) {\n scope.select({activeIdx:activeIdx});\n };\n }\n };\n }])\n \n .directive('typeaheadMatch', ['$templateRequest', '$compile', '$parse', '$typeaheadSuppressWarning', '$log', function($templateRequest, $compile, $parse, $typeaheadSuppressWarning, $log) {\n return {\n restrict: 'EA',\n scope: {\n index: '=',\n match: '=',\n query: '='\n },\n link:function(scope, element, attrs) {\n if (!$typeaheadSuppressWarning) {\n $log.warn('typeahead-match is now deprecated. Use uib-typeahead-match instead.');\n }\n\n var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html';\n $templateRequest(tplUrl).then(function(tplContent) {\n $compile(tplContent.trim())(scope, function(clonedElement) {\n element.replaceWith(clonedElement);\n });\n });\n }\n };\n }])\n \n .filter('typeaheadHighlight', ['$sce', '$injector', '$log', '$typeaheadSuppressWarning', function($sce, $injector, $log, $typeaheadSuppressWarning) {\n var isSanitizePresent;\n isSanitizePresent = $injector.has('$sanitize');\n\n function escapeRegexp(queryToEscape) {\n // Regex: capture the whole query string and replace it with the string that will be used to match\n // the results, for example if the capture is \"a\" the result will be \\a\n return queryToEscape.replace(/([.?*+^$[\\]\\\\(){}|-])/g, '\\\\$1');\n }\n\n function containsHtml(matchItem) {\n return /<.*>/g.test(matchItem);\n }\n\n return function(matchItem, query) {\n if (!$typeaheadSuppressWarning) {\n $log.warn('typeaheadHighlight is now deprecated. Use uibTypeaheadHighlight instead.');\n }\n\n if (!isSanitizePresent && containsHtml(matchItem)) {\n $log.warn('Unsafe use of typeahead please use ngSanitize'); // Warn the user about the danger\n }\n\n matchItem = query? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; // Replaces the capture string with a the same string inside of a \"strong\" tag\n if (!isSanitizePresent) {\n matchItem = $sce.trustAsHtml(matchItem); // If $sanitize is not present we pack the string in a $sce object for the ng-bind-html directive\n }\n\n return matchItem;\n };\n }]);\n\nangular.module(\"template/accordion/accordion-group.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/accordion/accordion-group.html\",\n \"\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \" {{heading}}\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"\t
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/accordion/accordion.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/accordion/accordion.html\",\n \"\");\n}]);\n\nangular.module(\"template/alert/alert.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/alert/alert.html\",\n \"\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/carousel/carousel.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/carousel/carousel.html\",\n \"\");\n}]);\n\nangular.module(\"template/carousel/slide.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/carousel/slide.html\",\n \"\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/datepicker/datepicker.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/datepicker/datepicker.html\",\n \"\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \"
\");\n}]);\n\nangular.module(\"template/datepicker/day.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/datepicker/day.html\",\n \"\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" | \\n\" +\n \" | \\n\" +\n \" | \\n\" +\n \"
\\n\" +\n \" \\n\" +\n \" | \\n\" +\n \" {{::label.abbr}} | \\n\" +\n \"
\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" {{ weekNumbers[$index] }} | \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" | \\n\" +\n \"
\\n\" +\n \" \\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/datepicker/month.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/datepicker/month.html\",\n \"
\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" | \\n\" +\n \" | \\n\" +\n \" | \\n\" +\n \"
\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" | \\n\" +\n \"
\\n\" +\n \" \\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/datepicker/popup.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/datepicker/popup.html\",\n \"\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/datepicker/year.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/datepicker/year.html\",\n \"
\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" | \\n\" +\n \" | \\n\" +\n \" | \\n\" +\n \"
\\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" \\n\" +\n \" | \\n\" +\n \"
\\n\" +\n \" \\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/modal/backdrop.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/modal/backdrop.html\",\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/modal/window.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/modal/window.html\",\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/pagination/pager.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/pagination/pager.html\",\n \"\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/pagination/pagination.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/pagination/pagination.html\",\n \"\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/tooltip/tooltip-html-popup.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/tooltip/tooltip-html-popup.html\",\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/tooltip/tooltip-popup.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/tooltip/tooltip-popup.html\",\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/tooltip/tooltip-template-popup.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/tooltip/tooltip-template-popup.html\",\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/popover/popover-html.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/popover/popover-html.html\",\n \"
\\n\" +\n \"
\\n\" +\n \"\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/popover/popover-template.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/popover/popover-template.html\",\n \"
\\n\" +\n \"
\\n\" +\n \"\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/popover/popover.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/popover/popover.html\",\n \"
\\n\" +\n \"
\\n\" +\n \"\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/progressbar/bar.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/progressbar/bar.html\",\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/progressbar/progress.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/progressbar/progress.html\",\n \"
\");\n}]);\n\nangular.module(\"template/progressbar/progressbar.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/progressbar/progressbar.html\",\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/rating/rating.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/rating/rating.html\",\n \"
\\n\" +\n \" ({{ $index < value ? '*' : ' ' }})\\n\" +\n \" \\n\" +\n \"\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/tabs/tab.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/tabs/tab.html\",\n \"
\\n\" +\n \" {{heading}}\\n\" +\n \"\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/tabs/tabset.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/tabs/tabset.html\",\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/timepicker/timepicker.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/timepicker/timepicker.html\",\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/typeahead/typeahead-match.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/typeahead/typeahead-match.html\",\n \"
\\n\" +\n \"\");\n}]);\n\nangular.module(\"template/typeahead/typeahead-popup.html\", []).run([\"$templateCache\", function($templateCache) {\n $templateCache.put(\"template/typeahead/typeahead-popup.html\",\n \"\\n\" +\n \"\");\n}]);\n!angular.$$csp() && angular.element(document).find('head').prepend('');\n(function() {\n 'use strict';\n\n angular.module('toastr', [])\n .factory('toastr', toastr);\n\n toastr.$inject = ['$animate', '$injector', '$document', '$rootScope', '$sce', 'toastrConfig', '$q'];\n\n function toastr($animate, $injector, $document, $rootScope, $sce, toastrConfig, $q) {\n var container;\n var index = 0;\n var toasts = [];\n\n var previousToastMessage = '';\n var openToasts = {};\n\n var containerDefer = $q.defer();\n\n var toast = {\n clear: clear,\n error: error,\n info: info,\n remove: remove,\n success: success,\n warning: warning\n };\n\n return toast;\n\n /* Public API */\n function clear(toast) {\n // Bit of a hack, I will remove this soon with a BC\n if (arguments.length === 1 && !toast) { return; }\n\n if (toast) {\n remove(toast.toastId);\n } else {\n for (var i = 0; i < toasts.length; i++) {\n remove(toasts[i].toastId);\n }\n }\n }\n\n function error(message, title, optionsOverride) {\n var type = _getOptions().iconClasses.error;\n return _buildNotification(type, message, title, optionsOverride);\n }\n\n function info(message, title, optionsOverride) {\n var type = _getOptions().iconClasses.info;\n return _buildNotification(type, message, title, optionsOverride);\n }\n\n function success(message, title, optionsOverride) {\n var type = _getOptions().iconClasses.success;\n return _buildNotification(type, message, title, optionsOverride);\n }\n\n function warning(message, title, optionsOverride) {\n var type = _getOptions().iconClasses.warning;\n return _buildNotification(type, message, title, optionsOverride);\n }\n\n function remove(toastId, wasClicked) {\n var toast = findToast(toastId);\n\n if (toast && ! toast.deleting) { // Avoid clicking when fading out\n toast.deleting = true;\n toast.isOpened = false;\n $animate.leave(toast.el).then(function() {\n if (toast.scope.options.onHidden) {\n toast.scope.options.onHidden(wasClicked);\n }\n toast.scope.$destroy();\n var index = toasts.indexOf(toast);\n delete openToasts[toast.scope.message];\n toasts.splice(index, 1);\n var maxOpened = toastrConfig.maxOpened;\n if (maxOpened && toasts.length >= maxOpened) {\n toasts[maxOpened - 1].open.resolve();\n }\n if (lastToast()) {\n container.remove();\n container = null;\n containerDefer = $q.defer();\n }\n });\n }\n\n function findToast(toastId) {\n for (var i = 0; i < toasts.length; i++) {\n if (toasts[i].toastId === toastId) {\n return toasts[i];\n }\n }\n }\n\n function lastToast() {\n return !toasts.length;\n }\n }\n\n /* Internal functions */\n function _buildNotification(type, message, title, optionsOverride)\n {\n if (angular.isObject(title)) {\n optionsOverride = title;\n title = null;\n }\n\n return _notify({\n iconClass: type,\n message: message,\n optionsOverride: optionsOverride,\n title: title\n });\n }\n\n function _getOptions() {\n return angular.extend({}, toastrConfig);\n }\n\n function _createOrGetContainer(options) {\n if(container) { return containerDefer.promise; }\n\n container = angular.element('
');\n container.attr('id', options.containerId);\n container.addClass(options.positionClass);\n container.css({'pointer-events': 'auto'});\n\n var target = angular.element(document.querySelector(options.target));\n\n if ( ! target || ! target.length) {\n throw 'Target for toasts doesn\\'t exist';\n }\n\n $animate.enter(container, target).then(function() {\n containerDefer.resolve();\n });\n\n return containerDefer.promise;\n }\n\n function _notify(map) {\n var options = _getOptions();\n\n if (shouldExit()) { return; }\n\n var newToast = createToast();\n\n toasts.push(newToast);\n\n if (ifMaxOpenedAndAutoDismiss()) {\n var oldToasts = toasts.slice(0, (toasts.length - options.maxOpened));\n for (var i = 0, len = oldToasts.length; i < len; i++) {\n remove(oldToasts[i].toastId);\n }\n }\n\n if (maxOpenedNotReached()) {\n newToast.open.resolve();\n }\n\n newToast.open.promise.then(function() {\n _createOrGetContainer(options).then(function() {\n newToast.isOpened = true;\n if (options.newestOnTop) {\n $animate.enter(newToast.el, container).then(function() {\n newToast.scope.init();\n });\n } else {\n var sibling = container[0].lastChild ? angular.element(container[0].lastChild) : null;\n $animate.enter(newToast.el, container, sibling).then(function() {\n newToast.scope.init();\n });\n }\n });\n });\n\n return newToast;\n\n function ifMaxOpenedAndAutoDismiss() {\n return options.autoDismiss && options.maxOpened && toasts.length > options.maxOpened;\n }\n\n function createScope(toast, map, options) {\n if (options.allowHtml) {\n toast.scope.allowHtml = true;\n toast.scope.title = $sce.trustAsHtml(map.title);\n toast.scope.message = $sce.trustAsHtml(map.message);\n } else {\n toast.scope.title = map.title;\n toast.scope.message = map.message;\n }\n\n toast.scope.toastType = toast.iconClass;\n toast.scope.toastId = toast.toastId;\n toast.scope.extraData = options.extraData;\n\n toast.scope.options = {\n extendedTimeOut: options.extendedTimeOut,\n messageClass: options.messageClass,\n onHidden: options.onHidden,\n onShown: options.onShown,\n onTap: options.onTap,\n progressBar: options.progressBar,\n tapToDismiss: options.tapToDismiss,\n timeOut: options.timeOut,\n titleClass: options.titleClass,\n toastClass: options.toastClass\n };\n\n if (options.closeButton) {\n toast.scope.options.closeHtml = options.closeHtml;\n }\n }\n\n function createToast() {\n var newToast = {\n toastId: index++,\n isOpened: false,\n scope: $rootScope.$new(),\n open: $q.defer()\n };\n newToast.iconClass = map.iconClass;\n if (map.optionsOverride) {\n angular.extend(options, cleanOptionsOverride(map.optionsOverride));\n newToast.iconClass = map.optionsOverride.iconClass || newToast.iconClass;\n }\n\n createScope(newToast, map, options);\n\n newToast.el = createToastEl(newToast.scope);\n\n return newToast;\n\n function cleanOptionsOverride(options) {\n var badOptions = ['containerId', 'iconClasses', 'maxOpened', 'newestOnTop',\n 'positionClass', 'preventDuplicates', 'preventOpenDuplicates', 'templates'];\n for (var i = 0, l = badOptions.length; i < l; i++) {\n delete options[badOptions[i]];\n }\n\n return options;\n }\n }\n\n function createToastEl(scope) {\n var angularDomEl = angular.element('
'),\n $compile = $injector.get('$compile');\n return $compile(angularDomEl)(scope);\n }\n\n function maxOpenedNotReached() {\n return options.maxOpened && toasts.length <= options.maxOpened || !options.maxOpened;\n }\n\n function shouldExit() {\n var isDuplicateOfLast = options.preventDuplicates && map.message === previousToastMessage;\n var isDuplicateOpen = options.preventOpenDuplicates && openToasts[map.message];\n\n if (isDuplicateOfLast || isDuplicateOpen) {\n return true;\n }\n\n previousToastMessage = map.message;\n openToasts[map.message] = true;\n\n return false;\n }\n }\n }\n}());\n\n(function() {\n 'use strict';\n\n angular.module('toastr')\n .constant('toastrConfig', {\n allowHtml: false,\n autoDismiss: false,\n closeButton: false,\n closeHtml: '
',\n containerId: 'toast-container',\n extendedTimeOut: 1000,\n iconClasses: {\n error: 'toast-error',\n info: 'toast-info',\n success: 'toast-success',\n warning: 'toast-warning'\n },\n maxOpened: 0,\n messageClass: 'toast-message',\n newestOnTop: true,\n onHidden: null,\n onShown: null,\n onTap: null,\n positionClass: 'toast-top-right',\n preventDuplicates: false,\n preventOpenDuplicates: false,\n progressBar: false,\n tapToDismiss: true,\n target: 'body',\n templates: {\n toast: 'directives/toast/toast.html',\n progressbar: 'directives/progressbar/progressbar.html'\n },\n timeOut: 5000,\n titleClass: 'toast-title',\n toastClass: 'toast'\n });\n}());\n\n(function() {\n 'use strict';\n\n angular.module('toastr')\n .directive('progressBar', progressBar);\n\n progressBar.$inject = ['toastrConfig'];\n\n function progressBar(toastrConfig) {\n return {\n replace: true,\n require: '^toast',\n templateUrl: function() {\n return toastrConfig.templates.progressbar;\n },\n link: linkFunction\n };\n\n function linkFunction(scope, element, attrs, toastCtrl) {\n var intervalId, currentTimeOut, hideTime;\n\n toastCtrl.progressBar = scope;\n\n scope.start = function(duration) {\n if (intervalId) {\n clearInterval(intervalId);\n }\n\n currentTimeOut = parseFloat(duration);\n hideTime = new Date().getTime() + currentTimeOut;\n intervalId = setInterval(updateProgress, 10);\n };\n\n scope.stop = function() {\n if (intervalId) {\n clearInterval(intervalId);\n }\n };\n\n function updateProgress() {\n var percentage = ((hideTime - (new Date().getTime())) / currentTimeOut) * 100;\n element.css('width', percentage + '%');\n }\n\n scope.$on('$destroy', function() {\n // Failsafe stop\n clearInterval(intervalId);\n });\n }\n }\n}());\n\n(function() {\n 'use strict';\n\n angular.module('toastr')\n .controller('ToastController', ToastController);\n\n function ToastController() {\n this.progressBar = null;\n\n this.startProgressBar = function(duration) {\n if (this.progressBar) {\n this.progressBar.start(duration);\n }\n };\n\n this.stopProgressBar = function() {\n if (this.progressBar) {\n this.progressBar.stop();\n }\n };\n }\n}());\n\n(function() {\n 'use strict';\n\n angular.module('toastr')\n .directive('toast', toast);\n\n toast.$inject = ['$injector', '$interval', 'toastrConfig', 'toastr'];\n\n function toast($injector, $interval, toastrConfig, toastr) {\n return {\n replace: true,\n templateUrl: function() {\n return toastrConfig.templates.toast;\n },\n controller: 'ToastController',\n link: toastLinkFunction\n };\n\n function toastLinkFunction(scope, element, attrs, toastCtrl) {\n var timeout;\n\n scope.toastClass = scope.options.toastClass;\n scope.titleClass = scope.options.titleClass;\n scope.messageClass = scope.options.messageClass;\n scope.progressBar = scope.options.progressBar;\n\n if (wantsCloseButton()) {\n var button = angular.element(scope.options.closeHtml),\n $compile = $injector.get('$compile');\n button.addClass('toast-close-button');\n button.attr('ng-click', 'close(true, $event)');\n $compile(button)(scope);\n element.prepend(button);\n }\n\n scope.init = function() {\n if (scope.options.timeOut) {\n timeout = createTimeout(scope.options.timeOut);\n }\n if (scope.options.onShown) {\n scope.options.onShown();\n }\n };\n\n element.on('mouseenter', function() {\n hideAndStopProgressBar();\n if (timeout) {\n $interval.cancel(timeout);\n }\n });\n\n scope.tapToast = function () {\n if (angular.isFunction(scope.options.onTap)) {\n scope.options.onTap();\n }\n if (scope.options.tapToDismiss) {\n scope.close(true);\n }\n };\n\n scope.close = function (wasClicked, $event) {\n if ($event && angular.isFunction($event.stopPropagation)) {\n $event.stopPropagation();\n }\n toastr.remove(scope.toastId, wasClicked);\n };\n\n element.on('mouseleave', function() {\n if (scope.options.timeOut === 0 && scope.options.extendedTimeOut === 0) { return; }\n scope.$apply(function() {\n scope.progressBar = scope.options.progressBar;\n });\n timeout = createTimeout(scope.options.extendedTimeOut);\n });\n\n function createTimeout(time) {\n toastCtrl.startProgressBar(time);\n return $interval(function() {\n toastCtrl.stopProgressBar();\n toastr.remove(scope.toastId);\n }, time, 1);\n }\n\n function hideAndStopProgressBar() {\n scope.progressBar = false;\n toastCtrl.stopProgressBar();\n }\n\n function wantsCloseButton() {\n return scope.options.closeHtml;\n }\n }\n }\n}());\n\nangular.module(\"toastr\").run([\"$templateCache\", function($templateCache) {$templateCache.put(\"directives/progressbar/progressbar.html\",\"
\\n\");\n$templateCache.put(\"directives/toast/toast.html\",\"
\\n
\\n
{{title}}
\\n
{{message}}
\\n
\\n
\\n
\\n
\\n
\\n\");}]);\n//! moment.js\n//! version : 2.10.6\n//! authors : Tim Wood, Iskren Chernev, Moment.js contributors\n//! license : MIT\n//! momentjs.com\n\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n global.moment = factory()\n}(this, function () { 'use strict';\n\n var hookCallback;\n\n function utils_hooks__hooks () {\n return hookCallback.apply(null, arguments);\n }\n\n // This is done to register the method called with moment()\n // without creating circular dependencies.\n function setHookCallback (callback) {\n hookCallback = callback;\n }\n\n function isArray(input) {\n return Object.prototype.toString.call(input) === '[object Array]';\n }\n\n function isDate(input) {\n return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';\n }\n\n function map(arr, fn) {\n var res = [], i;\n for (i = 0; i < arr.length; ++i) {\n res.push(fn(arr[i], i));\n }\n return res;\n }\n\n function hasOwnProp(a, b) {\n return Object.prototype.hasOwnProperty.call(a, b);\n }\n\n function extend(a, b) {\n for (var i in b) {\n if (hasOwnProp(b, i)) {\n a[i] = b[i];\n }\n }\n\n if (hasOwnProp(b, 'toString')) {\n a.toString = b.toString;\n }\n\n if (hasOwnProp(b, 'valueOf')) {\n a.valueOf = b.valueOf;\n }\n\n return a;\n }\n\n function create_utc__createUTC (input, format, locale, strict) {\n return createLocalOrUTC(input, format, locale, strict, true).utc();\n }\n\n function defaultParsingFlags() {\n // We need to deep clone this object.\n return {\n empty : false,\n unusedTokens : [],\n unusedInput : [],\n overflow : -2,\n charsLeftOver : 0,\n nullInput : false,\n invalidMonth : null,\n invalidFormat : false,\n userInvalidated : false,\n iso : false\n };\n }\n\n function getParsingFlags(m) {\n if (m._pf == null) {\n m._pf = defaultParsingFlags();\n }\n return m._pf;\n }\n\n function valid__isValid(m) {\n if (m._isValid == null) {\n var flags = getParsingFlags(m);\n m._isValid = !isNaN(m._d.getTime()) &&\n flags.overflow < 0 &&\n !flags.empty &&\n !flags.invalidMonth &&\n !flags.invalidWeekday &&\n !flags.nullInput &&\n !flags.invalidFormat &&\n !flags.userInvalidated;\n\n if (m._strict) {\n m._isValid = m._isValid &&\n flags.charsLeftOver === 0 &&\n flags.unusedTokens.length === 0 &&\n flags.bigHour === undefined;\n }\n }\n return m._isValid;\n }\n\n function valid__createInvalid (flags) {\n var m = create_utc__createUTC(NaN);\n if (flags != null) {\n extend(getParsingFlags(m), flags);\n }\n else {\n getParsingFlags(m).userInvalidated = true;\n }\n\n return m;\n }\n\n var momentProperties = utils_hooks__hooks.momentProperties = [];\n\n function copyConfig(to, from) {\n var i, prop, val;\n\n if (typeof from._isAMomentObject !== 'undefined') {\n to._isAMomentObject = from._isAMomentObject;\n }\n if (typeof from._i !== 'undefined') {\n to._i = from._i;\n }\n if (typeof from._f !== 'undefined') {\n to._f = from._f;\n }\n if (typeof from._l !== 'undefined') {\n to._l = from._l;\n }\n if (typeof from._strict !== 'undefined') {\n to._strict = from._strict;\n }\n if (typeof from._tzm !== 'undefined') {\n to._tzm = from._tzm;\n }\n if (typeof from._isUTC !== 'undefined') {\n to._isUTC = from._isUTC;\n }\n if (typeof from._offset !== 'undefined') {\n to._offset = from._offset;\n }\n if (typeof from._pf !== 'undefined') {\n to._pf = getParsingFlags(from);\n }\n if (typeof from._locale !== 'undefined') {\n to._locale = from._locale;\n }\n\n if (momentProperties.length > 0) {\n for (i in momentProperties) {\n prop = momentProperties[i];\n val = from[prop];\n if (typeof val !== 'undefined') {\n to[prop] = val;\n }\n }\n }\n\n return to;\n }\n\n var updateInProgress = false;\n\n // Moment prototype object\n function Moment(config) {\n copyConfig(this, config);\n this._d = new Date(config._d != null ? config._d.getTime() : NaN);\n // Prevent infinite loop in case updateOffset creates new moment\n // objects.\n if (updateInProgress === false) {\n updateInProgress = true;\n utils_hooks__hooks.updateOffset(this);\n updateInProgress = false;\n }\n }\n\n function isMoment (obj) {\n return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);\n }\n\n function absFloor (number) {\n if (number < 0) {\n return Math.ceil(number);\n } else {\n return Math.floor(number);\n }\n }\n\n function toInt(argumentForCoercion) {\n var coercedNumber = +argumentForCoercion,\n value = 0;\n\n if (coercedNumber !== 0 && isFinite(coercedNumber)) {\n value = absFloor(coercedNumber);\n }\n\n return value;\n }\n\n function compareArrays(array1, array2, dontConvert) {\n var len = Math.min(array1.length, array2.length),\n lengthDiff = Math.abs(array1.length - array2.length),\n diffs = 0,\n i;\n for (i = 0; i < len; i++) {\n if ((dontConvert && array1[i] !== array2[i]) ||\n (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {\n diffs++;\n }\n }\n return diffs + lengthDiff;\n }\n\n function Locale() {\n }\n\n var locales = {};\n var globalLocale;\n\n function normalizeLocale(key) {\n return key ? key.toLowerCase().replace('_', '-') : key;\n }\n\n // pick the locale from the array\n // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each\n // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root\n function chooseLocale(names) {\n var i = 0, j, next, locale, split;\n\n while (i < names.length) {\n split = normalizeLocale(names[i]).split('-');\n j = split.length;\n next = normalizeLocale(names[i + 1]);\n next = next ? next.split('-') : null;\n while (j > 0) {\n locale = loadLocale(split.slice(0, j).join('-'));\n if (locale) {\n return locale;\n }\n if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {\n //the next array item is better than a shallower substring of this one\n break;\n }\n j--;\n }\n i++;\n }\n return null;\n }\n\n function loadLocale(name) {\n var oldLocale = null;\n // TODO: Find a better way to register and load all the locales in Node\n if (!locales[name] && typeof module !== 'undefined' &&\n module && module.exports) {\n try {\n oldLocale = globalLocale._abbr;\n require('./locale/' + name);\n // because defineLocale currently also sets the global locale, we\n // want to undo that for lazy loaded locales\n locale_locales__getSetGlobalLocale(oldLocale);\n } catch (e) { }\n }\n return locales[name];\n }\n\n // This function will load locale and then set the global locale. If\n // no arguments are passed in, it will simply return the current global\n // locale key.\n function locale_locales__getSetGlobalLocale (key, values) {\n var data;\n if (key) {\n if (typeof values === 'undefined') {\n data = locale_locales__getLocale(key);\n }\n else {\n data = defineLocale(key, values);\n }\n\n if (data) {\n // moment.duration._locale = moment._locale = data;\n globalLocale = data;\n }\n }\n\n return globalLocale._abbr;\n }\n\n function defineLocale (name, values) {\n if (values !== null) {\n values.abbr = name;\n locales[name] = locales[name] || new Locale();\n locales[name].set(values);\n\n // backwards compat for now: also set the locale\n locale_locales__getSetGlobalLocale(name);\n\n return locales[name];\n } else {\n // useful for testing\n delete locales[name];\n return null;\n }\n }\n\n // returns locale data\n function locale_locales__getLocale (key) {\n var locale;\n\n if (key && key._locale && key._locale._abbr) {\n key = key._locale._abbr;\n }\n\n if (!key) {\n return globalLocale;\n }\n\n if (!isArray(key)) {\n //short-circuit everything else\n locale = loadLocale(key);\n if (locale) {\n return locale;\n }\n key = [key];\n }\n\n return chooseLocale(key);\n }\n\n var aliases = {};\n\n function addUnitAlias (unit, shorthand) {\n var lowerCase = unit.toLowerCase();\n aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;\n }\n\n function normalizeUnits(units) {\n return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;\n }\n\n function normalizeObjectUnits(inputObject) {\n var normalizedInput = {},\n normalizedProp,\n prop;\n\n for (prop in inputObject) {\n if (hasOwnProp(inputObject, prop)) {\n normalizedProp = normalizeUnits(prop);\n if (normalizedProp) {\n normalizedInput[normalizedProp] = inputObject[prop];\n }\n }\n }\n\n return normalizedInput;\n }\n\n function makeGetSet (unit, keepTime) {\n return function (value) {\n if (value != null) {\n get_set__set(this, unit, value);\n utils_hooks__hooks.updateOffset(this, keepTime);\n return this;\n } else {\n return get_set__get(this, unit);\n }\n };\n }\n\n function get_set__get (mom, unit) {\n return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]();\n }\n\n function get_set__set (mom, unit, value) {\n return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);\n }\n\n // MOMENTS\n\n function getSet (units, value) {\n var unit;\n if (typeof units === 'object') {\n for (unit in units) {\n this.set(unit, units[unit]);\n }\n } else {\n units = normalizeUnits(units);\n if (typeof this[units] === 'function') {\n return this[units](value);\n }\n }\n return this;\n }\n\n function zeroFill(number, targetLength, forceSign) {\n var absNumber = '' + Math.abs(number),\n zerosToFill = targetLength - absNumber.length,\n sign = number >= 0;\n return (sign ? (forceSign ? '+' : '') : '-') +\n Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;\n }\n\n var formattingTokens = /(\\[[^\\[]*\\])|(\\\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;\n\n var localFormattingTokens = /(\\[[^\\[]*\\])|(\\\\)?(LTS|LT|LL?L?L?|l{1,4})/g;\n\n var formatFunctions = {};\n\n var formatTokenFunctions = {};\n\n // token: 'M'\n // padded: ['MM', 2]\n // ordinal: 'Mo'\n // callback: function () { this.month() + 1 }\n function addFormatToken (token, padded, ordinal, callback) {\n var func = callback;\n if (typeof callback === 'string') {\n func = function () {\n return this[callback]();\n };\n }\n if (token) {\n formatTokenFunctions[token] = func;\n }\n if (padded) {\n formatTokenFunctions[padded[0]] = function () {\n return zeroFill(func.apply(this, arguments), padded[1], padded[2]);\n };\n }\n if (ordinal) {\n formatTokenFunctions[ordinal] = function () {\n return this.localeData().ordinal(func.apply(this, arguments), token);\n };\n }\n }\n\n function removeFormattingTokens(input) {\n if (input.match(/\\[[\\s\\S]/)) {\n return input.replace(/^\\[|\\]$/g, '');\n }\n return input.replace(/\\\\/g, '');\n }\n\n function makeFormatFunction(format) {\n var array = format.match(formattingTokens), i, length;\n\n for (i = 0, length = array.length; i < length; i++) {\n if (formatTokenFunctions[array[i]]) {\n array[i] = formatTokenFunctions[array[i]];\n } else {\n array[i] = removeFormattingTokens(array[i]);\n }\n }\n\n return function (mom) {\n var output = '';\n for (i = 0; i < length; i++) {\n output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];\n }\n return output;\n };\n }\n\n // format date using native date object\n function formatMoment(m, format) {\n if (!m.isValid()) {\n return m.localeData().invalidDate();\n }\n\n format = expandFormat(format, m.localeData());\n formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);\n\n return formatFunctions[format](m);\n }\n\n function expandFormat(format, locale) {\n var i = 5;\n\n function replaceLongDateFormatTokens(input) {\n return locale.longDateFormat(input) || input;\n }\n\n localFormattingTokens.lastIndex = 0;\n while (i >= 0 && localFormattingTokens.test(format)) {\n format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);\n localFormattingTokens.lastIndex = 0;\n i -= 1;\n }\n\n return format;\n }\n\n var match1 = /\\d/; // 0 - 9\n var match2 = /\\d\\d/; // 00 - 99\n var match3 = /\\d{3}/; // 000 - 999\n var match4 = /\\d{4}/; // 0000 - 9999\n var match6 = /[+-]?\\d{6}/; // -999999 - 999999\n var match1to2 = /\\d\\d?/; // 0 - 99\n var match1to3 = /\\d{1,3}/; // 0 - 999\n var match1to4 = /\\d{1,4}/; // 0 - 9999\n var match1to6 = /[+-]?\\d{1,6}/; // -999999 - 999999\n\n var matchUnsigned = /\\d+/; // 0 - inf\n var matchSigned = /[+-]?\\d+/; // -inf - inf\n\n var matchOffset = /Z|[+-]\\d\\d:?\\d\\d/gi; // +00:00 -00:00 +0000 -0000 or Z\n\n var matchTimestamp = /[+-]?\\d+(\\.\\d{1,3})?/; // 123456789 123456789.123\n\n // any word (or two) characters or numbers including two/three word month in arabic.\n var matchWord = /[0-9]*['a-z\\u00A0-\\u05FF\\u0700-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]+|[\\u0600-\\u06FF\\/]+(\\s*?[\\u0600-\\u06FF]+){1,2}/i;\n\n var regexes = {};\n\n function isFunction (sth) {\n // https://github.com/moment/moment/issues/2325\n return typeof sth === 'function' &&\n Object.prototype.toString.call(sth) === '[object Function]';\n }\n\n\n function addRegexToken (token, regex, strictRegex) {\n regexes[token] = isFunction(regex) ? regex : function (isStrict) {\n return (isStrict && strictRegex) ? strictRegex : regex;\n };\n }\n\n function getParseRegexForToken (token, config) {\n if (!hasOwnProp(regexes, token)) {\n return new RegExp(unescapeFormat(token));\n }\n\n return regexes[token](config._strict, config._locale);\n }\n\n // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript\n function unescapeFormat(s) {\n return s.replace('\\\\', '').replace(/\\\\(\\[)|\\\\(\\])|\\[([^\\]\\[]*)\\]|\\\\(.)/g, function (matched, p1, p2, p3, p4) {\n return p1 || p2 || p3 || p4;\n }).replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\n }\n\n var tokens = {};\n\n function addParseToken (token, callback) {\n var i, func = callback;\n if (typeof token === 'string') {\n token = [token];\n }\n if (typeof callback === 'number') {\n func = function (input, array) {\n array[callback] = toInt(input);\n };\n }\n for (i = 0; i < token.length; i++) {\n tokens[token[i]] = func;\n }\n }\n\n function addWeekParseToken (token, callback) {\n addParseToken(token, function (input, array, config, token) {\n config._w = config._w || {};\n callback(input, config._w, config, token);\n });\n }\n\n function addTimeToArrayFromToken(token, input, config) {\n if (input != null && hasOwnProp(tokens, token)) {\n tokens[token](input, config._a, config, token);\n }\n }\n\n var YEAR = 0;\n var MONTH = 1;\n var DATE = 2;\n var HOUR = 3;\n var MINUTE = 4;\n var SECOND = 5;\n var MILLISECOND = 6;\n\n function daysInMonth(year, month) {\n return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();\n }\n\n // FORMATTING\n\n addFormatToken('M', ['MM', 2], 'Mo', function () {\n return this.month() + 1;\n });\n\n addFormatToken('MMM', 0, 0, function (format) {\n return this.localeData().monthsShort(this, format);\n });\n\n addFormatToken('MMMM', 0, 0, function (format) {\n return this.localeData().months(this, format);\n });\n\n // ALIASES\n\n addUnitAlias('month', 'M');\n\n // PARSING\n\n addRegexToken('M', match1to2);\n addRegexToken('MM', match1to2, match2);\n addRegexToken('MMM', matchWord);\n addRegexToken('MMMM', matchWord);\n\n addParseToken(['M', 'MM'], function (input, array) {\n array[MONTH] = toInt(input) - 1;\n });\n\n addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {\n var month = config._locale.monthsParse(input, token, config._strict);\n // if we didn't find a month name, mark the date as invalid.\n if (month != null) {\n array[MONTH] = month;\n } else {\n getParsingFlags(config).invalidMonth = input;\n }\n });\n\n // LOCALES\n\n var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');\n function localeMonths (m) {\n return this._months[m.month()];\n }\n\n var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');\n function localeMonthsShort (m) {\n return this._monthsShort[m.month()];\n }\n\n function localeMonthsParse (monthName, format, strict) {\n var i, mom, regex;\n\n if (!this._monthsParse) {\n this._monthsParse = [];\n this._longMonthsParse = [];\n this._shortMonthsParse = [];\n }\n\n for (i = 0; i < 12; i++) {\n // make the regex if we don't have it already\n mom = create_utc__createUTC([2000, i]);\n if (strict && !this._longMonthsParse[i]) {\n this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');\n this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');\n }\n if (!strict && !this._monthsParse[i]) {\n regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');\n this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');\n }\n // test the regex\n if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {\n return i;\n } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {\n return i;\n } else if (!strict && this._monthsParse[i].test(monthName)) {\n return i;\n }\n }\n }\n\n // MOMENTS\n\n function setMonth (mom, value) {\n var dayOfMonth;\n\n // TODO: Move this out of here!\n if (typeof value === 'string') {\n value = mom.localeData().monthsParse(value);\n // TODO: Another silent failure?\n if (typeof value !== 'number') {\n return mom;\n }\n }\n\n dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));\n mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);\n return mom;\n }\n\n function getSetMonth (value) {\n if (value != null) {\n setMonth(this, value);\n utils_hooks__hooks.updateOffset(this, true);\n return this;\n } else {\n return get_set__get(this, 'Month');\n }\n }\n\n function getDaysInMonth () {\n return daysInMonth(this.year(), this.month());\n }\n\n function checkOverflow (m) {\n var overflow;\n var a = m._a;\n\n if (a && getParsingFlags(m).overflow === -2) {\n overflow =\n a[MONTH] < 0 || a[MONTH] > 11 ? MONTH :\n a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE :\n a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :\n a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE :\n a[SECOND] < 0 || a[SECOND] > 59 ? SECOND :\n a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :\n -1;\n\n if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {\n overflow = DATE;\n }\n\n getParsingFlags(m).overflow = overflow;\n }\n\n return m;\n }\n\n function warn(msg) {\n if (utils_hooks__hooks.suppressDeprecationWarnings === false && typeof console !== 'undefined' && console.warn) {\n console.warn('Deprecation warning: ' + msg);\n }\n }\n\n function deprecate(msg, fn) {\n var firstTime = true;\n\n return extend(function () {\n if (firstTime) {\n warn(msg + '\\n' + (new Error()).stack);\n firstTime = false;\n }\n return fn.apply(this, arguments);\n }, fn);\n }\n\n var deprecations = {};\n\n function deprecateSimple(name, msg) {\n if (!deprecations[name]) {\n warn(msg);\n deprecations[name] = true;\n }\n }\n\n utils_hooks__hooks.suppressDeprecationWarnings = false;\n\n var from_string__isoRegex = /^\\s*(?:[+-]\\d{6}|\\d{4})-(?:(\\d\\d-\\d\\d)|(W\\d\\d$)|(W\\d\\d-\\d)|(\\d\\d\\d))((T| )(\\d\\d(:\\d\\d(:\\d\\d(\\.\\d+)?)?)?)?([\\+\\-]\\d\\d(?::?\\d\\d)?|\\s*Z)?)?$/;\n\n var isoDates = [\n ['YYYYYY-MM-DD', /[+-]\\d{6}-\\d{2}-\\d{2}/],\n ['YYYY-MM-DD', /\\d{4}-\\d{2}-\\d{2}/],\n ['GGGG-[W]WW-E', /\\d{4}-W\\d{2}-\\d/],\n ['GGGG-[W]WW', /\\d{4}-W\\d{2}/],\n ['YYYY-DDD', /\\d{4}-\\d{3}/]\n ];\n\n // iso time formats and regexes\n var isoTimes = [\n ['HH:mm:ss.SSSS', /(T| )\\d\\d:\\d\\d:\\d\\d\\.\\d+/],\n ['HH:mm:ss', /(T| )\\d\\d:\\d\\d:\\d\\d/],\n ['HH:mm', /(T| )\\d\\d:\\d\\d/],\n ['HH', /(T| )\\d\\d/]\n ];\n\n var aspNetJsonRegex = /^\\/?Date\\((\\-?\\d+)/i;\n\n // date from iso format\n function configFromISO(config) {\n var i, l,\n string = config._i,\n match = from_string__isoRegex.exec(string);\n\n if (match) {\n getParsingFlags(config).iso = true;\n for (i = 0, l = isoDates.length; i < l; i++) {\n if (isoDates[i][1].exec(string)) {\n config._f = isoDates[i][0];\n break;\n }\n }\n for (i = 0, l = isoTimes.length; i < l; i++) {\n if (isoTimes[i][1].exec(string)) {\n // match[6] should be 'T' or space\n config._f += (match[6] || ' ') + isoTimes[i][0];\n break;\n }\n }\n if (string.match(matchOffset)) {\n config._f += 'Z';\n }\n configFromStringAndFormat(config);\n } else {\n config._isValid = false;\n }\n }\n\n // date from iso format or fallback\n function configFromString(config) {\n var matched = aspNetJsonRegex.exec(config._i);\n\n if (matched !== null) {\n config._d = new Date(+matched[1]);\n return;\n }\n\n configFromISO(config);\n if (config._isValid === false) {\n delete config._isValid;\n utils_hooks__hooks.createFromInputFallback(config);\n }\n }\n\n utils_hooks__hooks.createFromInputFallback = deprecate(\n 'moment construction falls back to js Date. This is ' +\n 'discouraged and will be removed in upcoming major ' +\n 'release. Please refer to ' +\n 'https://github.com/moment/moment/issues/1407 for more info.',\n function (config) {\n config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));\n }\n );\n\n function createDate (y, m, d, h, M, s, ms) {\n //can't just apply() to create a date:\n //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply\n var date = new Date(y, m, d, h, M, s, ms);\n\n //the date constructor doesn't accept years < 1970\n if (y < 1970) {\n date.setFullYear(y);\n }\n return date;\n }\n\n function createUTCDate (y) {\n var date = new Date(Date.UTC.apply(null, arguments));\n if (y < 1970) {\n date.setUTCFullYear(y);\n }\n return date;\n }\n\n addFormatToken(0, ['YY', 2], 0, function () {\n return this.year() % 100;\n });\n\n addFormatToken(0, ['YYYY', 4], 0, 'year');\n addFormatToken(0, ['YYYYY', 5], 0, 'year');\n addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');\n\n // ALIASES\n\n addUnitAlias('year', 'y');\n\n // PARSING\n\n addRegexToken('Y', matchSigned);\n addRegexToken('YY', match1to2, match2);\n addRegexToken('YYYY', match1to4, match4);\n addRegexToken('YYYYY', match1to6, match6);\n addRegexToken('YYYYYY', match1to6, match6);\n\n addParseToken(['YYYYY', 'YYYYYY'], YEAR);\n addParseToken('YYYY', function (input, array) {\n array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input);\n });\n addParseToken('YY', function (input, array) {\n array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);\n });\n\n // HELPERS\n\n function daysInYear(year) {\n return isLeapYear(year) ? 366 : 365;\n }\n\n function isLeapYear(year) {\n return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n }\n\n // HOOKS\n\n utils_hooks__hooks.parseTwoDigitYear = function (input) {\n return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);\n };\n\n // MOMENTS\n\n var getSetYear = makeGetSet('FullYear', false);\n\n function getIsLeapYear () {\n return isLeapYear(this.year());\n }\n\n addFormatToken('w', ['ww', 2], 'wo', 'week');\n addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');\n\n // ALIASES\n\n addUnitAlias('week', 'w');\n addUnitAlias('isoWeek', 'W');\n\n // PARSING\n\n addRegexToken('w', match1to2);\n addRegexToken('ww', match1to2, match2);\n addRegexToken('W', match1to2);\n addRegexToken('WW', match1to2, match2);\n\n addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {\n week[token.substr(0, 1)] = toInt(input);\n });\n\n // HELPERS\n\n // firstDayOfWeek 0 = sun, 6 = sat\n // the day of the week that starts the week\n // (usually sunday or monday)\n // firstDayOfWeekOfYear 0 = sun, 6 = sat\n // the first week is the week that contains the first\n // of this day of the week\n // (eg. ISO weeks use thursday (4))\n function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {\n var end = firstDayOfWeekOfYear - firstDayOfWeek,\n daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),\n adjustedMoment;\n\n\n if (daysToDayOfWeek > end) {\n daysToDayOfWeek -= 7;\n }\n\n if (daysToDayOfWeek < end - 7) {\n daysToDayOfWeek += 7;\n }\n\n adjustedMoment = local__createLocal(mom).add(daysToDayOfWeek, 'd');\n return {\n week: Math.ceil(adjustedMoment.dayOfYear() / 7),\n year: adjustedMoment.year()\n };\n }\n\n // LOCALES\n\n function localeWeek (mom) {\n return weekOfYear(mom, this._week.dow, this._week.doy).week;\n }\n\n var defaultLocaleWeek = {\n dow : 0, // Sunday is the first day of the week.\n doy : 6 // The week that contains Jan 1st is the first week of the year.\n };\n\n function localeFirstDayOfWeek () {\n return this._week.dow;\n }\n\n function localeFirstDayOfYear () {\n return this._week.doy;\n }\n\n // MOMENTS\n\n function getSetWeek (input) {\n var week = this.localeData().week(this);\n return input == null ? week : this.add((input - week) * 7, 'd');\n }\n\n function getSetISOWeek (input) {\n var week = weekOfYear(this, 1, 4).week;\n return input == null ? week : this.add((input - week) * 7, 'd');\n }\n\n addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');\n\n // ALIASES\n\n addUnitAlias('dayOfYear', 'DDD');\n\n // PARSING\n\n addRegexToken('DDD', match1to3);\n addRegexToken('DDDD', match3);\n addParseToken(['DDD', 'DDDD'], function (input, array, config) {\n config._dayOfYear = toInt(input);\n });\n\n // HELPERS\n\n //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday\n function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {\n var week1Jan = 6 + firstDayOfWeek - firstDayOfWeekOfYear, janX = createUTCDate(year, 0, 1 + week1Jan), d = janX.getUTCDay(), dayOfYear;\n if (d < firstDayOfWeek) {\n d += 7;\n }\n\n weekday = weekday != null ? 1 * weekday : firstDayOfWeek;\n\n dayOfYear = 1 + week1Jan + 7 * (week - 1) - d + weekday;\n\n return {\n year: dayOfYear > 0 ? year : year - 1,\n dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear\n };\n }\n\n // MOMENTS\n\n function getSetDayOfYear (input) {\n var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;\n return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');\n }\n\n // Pick the first defined of two or three arguments.\n function defaults(a, b, c) {\n if (a != null) {\n return a;\n }\n if (b != null) {\n return b;\n }\n return c;\n }\n\n function currentDateArray(config) {\n var now = new Date();\n if (config._useUTC) {\n return [now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()];\n }\n return [now.getFullYear(), now.getMonth(), now.getDate()];\n }\n\n // convert an array to a date.\n // the array should mirror the parameters below\n // note: all values past the year are optional and will default to the lowest possible value.\n // [year, month, day , hour, minute, second, millisecond]\n function configFromArray (config) {\n var i, date, input = [], currentDate, yearToUse;\n\n if (config._d) {\n return;\n }\n\n currentDate = currentDateArray(config);\n\n //compute day of the year from weeks and weekdays\n if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {\n dayOfYearFromWeekInfo(config);\n }\n\n //if the day of the year is set, figure out what it is\n if (config._dayOfYear) {\n yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);\n\n if (config._dayOfYear > daysInYear(yearToUse)) {\n getParsingFlags(config)._overflowDayOfYear = true;\n }\n\n date = createUTCDate(yearToUse, 0, config._dayOfYear);\n config._a[MONTH] = date.getUTCMonth();\n config._a[DATE] = date.getUTCDate();\n }\n\n // Default to current date.\n // * if no year, month, day of month are given, default to today\n // * if day of month is given, default month and year\n // * if month is given, default only year\n // * if year is given, don't default anything\n for (i = 0; i < 3 && config._a[i] == null; ++i) {\n config._a[i] = input[i] = currentDate[i];\n }\n\n // Zero out whatever was not defaulted, including time\n for (; i < 7; i++) {\n config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];\n }\n\n // Check for 24:00:00.000\n if (config._a[HOUR] === 24 &&\n config._a[MINUTE] === 0 &&\n config._a[SECOND] === 0 &&\n config._a[MILLISECOND] === 0) {\n config._nextDay = true;\n config._a[HOUR] = 0;\n }\n\n config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);\n // Apply timezone offset from input. The actual utcOffset can be changed\n // with parseZone.\n if (config._tzm != null) {\n config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);\n }\n\n if (config._nextDay) {\n config._a[HOUR] = 24;\n }\n }\n\n function dayOfYearFromWeekInfo(config) {\n var w, weekYear, week, weekday, dow, doy, temp;\n\n w = config._w;\n if (w.GG != null || w.W != null || w.E != null) {\n dow = 1;\n doy = 4;\n\n // TODO: We need to take the current isoWeekYear, but that depends on\n // how we interpret now (local, utc, fixed offset). So create\n // a now version of current config (take local/utc/offset flags, and\n // create now).\n weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);\n week = defaults(w.W, 1);\n weekday = defaults(w.E, 1);\n } else {\n dow = config._locale._week.dow;\n doy = config._locale._week.doy;\n\n weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);\n week = defaults(w.w, 1);\n\n if (w.d != null) {\n // weekday -- low day numbers are considered next week\n weekday = w.d;\n if (weekday < dow) {\n ++week;\n }\n } else if (w.e != null) {\n // local weekday -- counting starts from begining of week\n weekday = w.e + dow;\n } else {\n // default to begining of week\n weekday = dow;\n }\n }\n temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow);\n\n config._a[YEAR] = temp.year;\n config._dayOfYear = temp.dayOfYear;\n }\n\n utils_hooks__hooks.ISO_8601 = function () {};\n\n // date from string and format string\n function configFromStringAndFormat(config) {\n // TODO: Move this to another part of the creation flow to prevent circular deps\n if (config._f === utils_hooks__hooks.ISO_8601) {\n configFromISO(config);\n return;\n }\n\n config._a = [];\n getParsingFlags(config).empty = true;\n\n // This array is used to make a Date, either with `new Date` or `Date.UTC`\n var string = '' + config._i,\n i, parsedInput, tokens, token, skipped,\n stringLength = string.length,\n totalParsedInputLength = 0;\n\n tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];\n\n for (i = 0; i < tokens.length; i++) {\n token = tokens[i];\n parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];\n if (parsedInput) {\n skipped = string.substr(0, string.indexOf(parsedInput));\n if (skipped.length > 0) {\n getParsingFlags(config).unusedInput.push(skipped);\n }\n string = string.slice(string.indexOf(parsedInput) + parsedInput.length);\n totalParsedInputLength += parsedInput.length;\n }\n // don't parse if it's not a known token\n if (formatTokenFunctions[token]) {\n if (parsedInput) {\n getParsingFlags(config).empty = false;\n }\n else {\n getParsingFlags(config).unusedTokens.push(token);\n }\n addTimeToArrayFromToken(token, parsedInput, config);\n }\n else if (config._strict && !parsedInput) {\n getParsingFlags(config).unusedTokens.push(token);\n }\n }\n\n // add remaining unparsed input length to the string\n getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;\n if (string.length > 0) {\n getParsingFlags(config).unusedInput.push(string);\n }\n\n // clear _12h flag if hour is <= 12\n if (getParsingFlags(config).bigHour === true &&\n config._a[HOUR] <= 12 &&\n config._a[HOUR] > 0) {\n getParsingFlags(config).bigHour = undefined;\n }\n // handle meridiem\n config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);\n\n configFromArray(config);\n checkOverflow(config);\n }\n\n\n function meridiemFixWrap (locale, hour, meridiem) {\n var isPm;\n\n if (meridiem == null) {\n // nothing to do\n return hour;\n }\n if (locale.meridiemHour != null) {\n return locale.meridiemHour(hour, meridiem);\n } else if (locale.isPM != null) {\n // Fallback\n isPm = locale.isPM(meridiem);\n if (isPm && hour < 12) {\n hour += 12;\n }\n if (!isPm && hour === 12) {\n hour = 0;\n }\n return hour;\n } else {\n // this is not supposed to happen\n return hour;\n }\n }\n\n function configFromStringAndArray(config) {\n var tempConfig,\n bestMoment,\n\n scoreToBeat,\n i,\n currentScore;\n\n if (config._f.length === 0) {\n getParsingFlags(config).invalidFormat = true;\n config._d = new Date(NaN);\n return;\n }\n\n for (i = 0; i < config._f.length; i++) {\n currentScore = 0;\n tempConfig = copyConfig({}, config);\n if (config._useUTC != null) {\n tempConfig._useUTC = config._useUTC;\n }\n tempConfig._f = config._f[i];\n configFromStringAndFormat(tempConfig);\n\n if (!valid__isValid(tempConfig)) {\n continue;\n }\n\n // if there is any input that was not parsed add a penalty for that format\n currentScore += getParsingFlags(tempConfig).charsLeftOver;\n\n //or tokens\n currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;\n\n getParsingFlags(tempConfig).score = currentScore;\n\n if (scoreToBeat == null || currentScore < scoreToBeat) {\n scoreToBeat = currentScore;\n bestMoment = tempConfig;\n }\n }\n\n extend(config, bestMoment || tempConfig);\n }\n\n function configFromObject(config) {\n if (config._d) {\n return;\n }\n\n var i = normalizeObjectUnits(config._i);\n config._a = [i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond];\n\n configFromArray(config);\n }\n\n function createFromConfig (config) {\n var res = new Moment(checkOverflow(prepareConfig(config)));\n if (res._nextDay) {\n // Adding is smart enough around DST\n res.add(1, 'd');\n res._nextDay = undefined;\n }\n\n return res;\n }\n\n function prepareConfig (config) {\n var input = config._i,\n format = config._f;\n\n config._locale = config._locale || locale_locales__getLocale(config._l);\n\n if (input === null || (format === undefined && input === '')) {\n return valid__createInvalid({nullInput: true});\n }\n\n if (typeof input === 'string') {\n config._i = input = config._locale.preparse(input);\n }\n\n if (isMoment(input)) {\n return new Moment(checkOverflow(input));\n } else if (isArray(format)) {\n configFromStringAndArray(config);\n } else if (format) {\n configFromStringAndFormat(config);\n } else if (isDate(input)) {\n config._d = input;\n } else {\n configFromInput(config);\n }\n\n return config;\n }\n\n function configFromInput(config) {\n var input = config._i;\n if (input === undefined) {\n config._d = new Date();\n } else if (isDate(input)) {\n config._d = new Date(+input);\n } else if (typeof input === 'string') {\n configFromString(config);\n } else if (isArray(input)) {\n config._a = map(input.slice(0), function (obj) {\n return parseInt(obj, 10);\n });\n configFromArray(config);\n } else if (typeof(input) === 'object') {\n configFromObject(config);\n } else if (typeof(input) === 'number') {\n // from milliseconds\n config._d = new Date(input);\n } else {\n utils_hooks__hooks.createFromInputFallback(config);\n }\n }\n\n function createLocalOrUTC (input, format, locale, strict, isUTC) {\n var c = {};\n\n if (typeof(locale) === 'boolean') {\n strict = locale;\n locale = undefined;\n }\n // object construction must be done this way.\n // https://github.com/moment/moment/issues/1423\n c._isAMomentObject = true;\n c._useUTC = c._isUTC = isUTC;\n c._l = locale;\n c._i = input;\n c._f = format;\n c._strict = strict;\n\n return createFromConfig(c);\n }\n\n function local__createLocal (input, format, locale, strict) {\n return createLocalOrUTC(input, format, locale, strict, false);\n }\n\n var prototypeMin = deprecate(\n 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',\n function () {\n var other = local__createLocal.apply(null, arguments);\n return other < this ? this : other;\n }\n );\n\n var prototypeMax = deprecate(\n 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',\n function () {\n var other = local__createLocal.apply(null, arguments);\n return other > this ? this : other;\n }\n );\n\n // Pick a moment m from moments so that m[fn](other) is true for all\n // other. This relies on the function fn to be transitive.\n //\n // moments should either be an array of moment objects or an array, whose\n // first element is an array of moment objects.\n function pickBy(fn, moments) {\n var res, i;\n if (moments.length === 1 && isArray(moments[0])) {\n moments = moments[0];\n }\n if (!moments.length) {\n return local__createLocal();\n }\n res = moments[0];\n for (i = 1; i < moments.length; ++i) {\n if (!moments[i].isValid() || moments[i][fn](res)) {\n res = moments[i];\n }\n }\n return res;\n }\n\n // TODO: Use [].sort instead?\n function min () {\n var args = [].slice.call(arguments, 0);\n\n return pickBy('isBefore', args);\n }\n\n function max () {\n var args = [].slice.call(arguments, 0);\n\n return pickBy('isAfter', args);\n }\n\n function Duration (duration) {\n var normalizedInput = normalizeObjectUnits(duration),\n years = normalizedInput.year || 0,\n quarters = normalizedInput.quarter || 0,\n months = normalizedInput.month || 0,\n weeks = normalizedInput.week || 0,\n days = normalizedInput.day || 0,\n hours = normalizedInput.hour || 0,\n minutes = normalizedInput.minute || 0,\n seconds = normalizedInput.second || 0,\n milliseconds = normalizedInput.millisecond || 0;\n\n // representation for dateAddRemove\n this._milliseconds = +milliseconds +\n seconds * 1e3 + // 1000\n minutes * 6e4 + // 1000 * 60\n hours * 36e5; // 1000 * 60 * 60\n // Because of dateAddRemove treats 24 hours as different from a\n // day when working around DST, we need to store them separately\n this._days = +days +\n weeks * 7;\n // It is impossible translate months into days without knowing\n // which months you are are talking about, so we have to store\n // it separately.\n this._months = +months +\n quarters * 3 +\n years * 12;\n\n this._data = {};\n\n this._locale = locale_locales__getLocale();\n\n this._bubble();\n }\n\n function isDuration (obj) {\n return obj instanceof Duration;\n }\n\n function offset (token, separator) {\n addFormatToken(token, 0, 0, function () {\n var offset = this.utcOffset();\n var sign = '+';\n if (offset < 0) {\n offset = -offset;\n sign = '-';\n }\n return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);\n });\n }\n\n offset('Z', ':');\n offset('ZZ', '');\n\n // PARSING\n\n addRegexToken('Z', matchOffset);\n addRegexToken('ZZ', matchOffset);\n addParseToken(['Z', 'ZZ'], function (input, array, config) {\n config._useUTC = true;\n config._tzm = offsetFromString(input);\n });\n\n // HELPERS\n\n // timezone chunker\n // '+10:00' > ['10', '00']\n // '-1530' > ['-15', '30']\n var chunkOffset = /([\\+\\-]|\\d\\d)/gi;\n\n function offsetFromString(string) {\n var matches = ((string || '').match(matchOffset) || []);\n var chunk = matches[matches.length - 1] || [];\n var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];\n var minutes = +(parts[1] * 60) + toInt(parts[2]);\n\n return parts[0] === '+' ? minutes : -minutes;\n }\n\n // Return a moment from input, that is local/utc/zone equivalent to model.\n function cloneWithOffset(input, model) {\n var res, diff;\n if (model._isUTC) {\n res = model.clone();\n diff = (isMoment(input) || isDate(input) ? +input : +local__createLocal(input)) - (+res);\n // Use low-level api, because this fn is low-level api.\n res._d.setTime(+res._d + diff);\n utils_hooks__hooks.updateOffset(res, false);\n return res;\n } else {\n return local__createLocal(input).local();\n }\n }\n\n function getDateOffset (m) {\n // On Firefox.24 Date#getTimezoneOffset returns a floating point.\n // https://github.com/moment/moment/pull/1871\n return -Math.round(m._d.getTimezoneOffset() / 15) * 15;\n }\n\n // HOOKS\n\n // This function will be called whenever a moment is mutated.\n // It is intended to keep the offset in sync with the timezone.\n utils_hooks__hooks.updateOffset = function () {};\n\n // MOMENTS\n\n // keepLocalTime = true means only change the timezone, without\n // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->\n // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset\n // +0200, so we adjust the time as needed, to be valid.\n //\n // Keeping the time actually adds/subtracts (one hour)\n // from the actual represented time. That is why we call updateOffset\n // a second time. In case it wants us to change the offset again\n // _changeInProgress == true case, then we have to adjust, because\n // there is no such time in the given timezone.\n function getSetOffset (input, keepLocalTime) {\n var offset = this._offset || 0,\n localAdjust;\n if (input != null) {\n if (typeof input === 'string') {\n input = offsetFromString(input);\n }\n if (Math.abs(input) < 16) {\n input = input * 60;\n }\n if (!this._isUTC && keepLocalTime) {\n localAdjust = getDateOffset(this);\n }\n this._offset = input;\n this._isUTC = true;\n if (localAdjust != null) {\n this.add(localAdjust, 'm');\n }\n if (offset !== input) {\n if (!keepLocalTime || this._changeInProgress) {\n add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);\n } else if (!this._changeInProgress) {\n this._changeInProgress = true;\n utils_hooks__hooks.updateOffset(this, true);\n this._changeInProgress = null;\n }\n }\n return this;\n } else {\n return this._isUTC ? offset : getDateOffset(this);\n }\n }\n\n function getSetZone (input, keepLocalTime) {\n if (input != null) {\n if (typeof input !== 'string') {\n input = -input;\n }\n\n this.utcOffset(input, keepLocalTime);\n\n return this;\n } else {\n return -this.utcOffset();\n }\n }\n\n function setOffsetToUTC (keepLocalTime) {\n return this.utcOffset(0, keepLocalTime);\n }\n\n function setOffsetToLocal (keepLocalTime) {\n if (this._isUTC) {\n this.utcOffset(0, keepLocalTime);\n this._isUTC = false;\n\n if (keepLocalTime) {\n this.subtract(getDateOffset(this), 'm');\n }\n }\n return this;\n }\n\n function setOffsetToParsedOffset () {\n if (this._tzm) {\n this.utcOffset(this._tzm);\n } else if (typeof this._i === 'string') {\n this.utcOffset(offsetFromString(this._i));\n }\n return this;\n }\n\n function hasAlignedHourOffset (input) {\n input = input ? local__createLocal(input).utcOffset() : 0;\n\n return (this.utcOffset() - input) % 60 === 0;\n }\n\n function isDaylightSavingTime () {\n return (\n this.utcOffset() > this.clone().month(0).utcOffset() ||\n this.utcOffset() > this.clone().month(5).utcOffset()\n );\n }\n\n function isDaylightSavingTimeShifted () {\n if (typeof this._isDSTShifted !== 'undefined') {\n return this._isDSTShifted;\n }\n\n var c = {};\n\n copyConfig(c, this);\n c = prepareConfig(c);\n\n if (c._a) {\n var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a);\n this._isDSTShifted = this.isValid() &&\n compareArrays(c._a, other.toArray()) > 0;\n } else {\n this._isDSTShifted = false;\n }\n\n return this._isDSTShifted;\n }\n\n function isLocal () {\n return !this._isUTC;\n }\n\n function isUtcOffset () {\n return this._isUTC;\n }\n\n function isUtc () {\n return this._isUTC && this._offset === 0;\n }\n\n var aspNetRegex = /(\\-)?(?:(\\d*)\\.)?(\\d+)\\:(\\d+)(?:\\:(\\d+)\\.?(\\d{3})?)?/;\n\n // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html\n // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere\n var create__isoRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;\n\n function create__createDuration (input, key) {\n var duration = input,\n // matching against regexp is expensive, do it on demand\n match = null,\n sign,\n ret,\n diffRes;\n\n if (isDuration(input)) {\n duration = {\n ms : input._milliseconds,\n d : input._days,\n M : input._months\n };\n } else if (typeof input === 'number') {\n duration = {};\n if (key) {\n duration[key] = input;\n } else {\n duration.milliseconds = input;\n }\n } else if (!!(match = aspNetRegex.exec(input))) {\n sign = (match[1] === '-') ? -1 : 1;\n duration = {\n y : 0,\n d : toInt(match[DATE]) * sign,\n h : toInt(match[HOUR]) * sign,\n m : toInt(match[MINUTE]) * sign,\n s : toInt(match[SECOND]) * sign,\n ms : toInt(match[MILLISECOND]) * sign\n };\n } else if (!!(match = create__isoRegex.exec(input))) {\n sign = (match[1] === '-') ? -1 : 1;\n duration = {\n y : parseIso(match[2], sign),\n M : parseIso(match[3], sign),\n d : parseIso(match[4], sign),\n h : parseIso(match[5], sign),\n m : parseIso(match[6], sign),\n s : parseIso(match[7], sign),\n w : parseIso(match[8], sign)\n };\n } else if (duration == null) {// checks for null or undefined\n duration = {};\n } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {\n diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));\n\n duration = {};\n duration.ms = diffRes.milliseconds;\n duration.M = diffRes.months;\n }\n\n ret = new Duration(duration);\n\n if (isDuration(input) && hasOwnProp(input, '_locale')) {\n ret._locale = input._locale;\n }\n\n return ret;\n }\n\n create__createDuration.fn = Duration.prototype;\n\n function parseIso (inp, sign) {\n // We'd normally use ~~inp for this, but unfortunately it also\n // converts floats to ints.\n // inp may be undefined, so careful calling replace on it.\n var res = inp && parseFloat(inp.replace(',', '.'));\n // apply sign while we're at it\n return (isNaN(res) ? 0 : res) * sign;\n }\n\n function positiveMomentsDifference(base, other) {\n var res = {milliseconds: 0, months: 0};\n\n res.months = other.month() - base.month() +\n (other.year() - base.year()) * 12;\n if (base.clone().add(res.months, 'M').isAfter(other)) {\n --res.months;\n }\n\n res.milliseconds = +other - +(base.clone().add(res.months, 'M'));\n\n return res;\n }\n\n function momentsDifference(base, other) {\n var res;\n other = cloneWithOffset(other, base);\n if (base.isBefore(other)) {\n res = positiveMomentsDifference(base, other);\n } else {\n res = positiveMomentsDifference(other, base);\n res.milliseconds = -res.milliseconds;\n res.months = -res.months;\n }\n\n return res;\n }\n\n function createAdder(direction, name) {\n return function (val, period) {\n var dur, tmp;\n //invert the arguments, but complain about it\n if (period !== null && !isNaN(+period)) {\n deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');\n tmp = val; val = period; period = tmp;\n }\n\n val = typeof val === 'string' ? +val : val;\n dur = create__createDuration(val, period);\n add_subtract__addSubtract(this, dur, direction);\n return this;\n };\n }\n\n function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {\n var milliseconds = duration._milliseconds,\n days = duration._days,\n months = duration._months;\n updateOffset = updateOffset == null ? true : updateOffset;\n\n if (milliseconds) {\n mom._d.setTime(+mom._d + milliseconds * isAdding);\n }\n if (days) {\n get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);\n }\n if (months) {\n setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);\n }\n if (updateOffset) {\n utils_hooks__hooks.updateOffset(mom, days || months);\n }\n }\n\n var add_subtract__add = createAdder(1, 'add');\n var add_subtract__subtract = createAdder(-1, 'subtract');\n\n function moment_calendar__calendar (time, formats) {\n // We want to compare the start of today, vs this.\n // Getting start-of-today depends on whether we're local/utc/offset or not.\n var now = time || local__createLocal(),\n sod = cloneWithOffset(now, this).startOf('day'),\n diff = this.diff(sod, 'days', true),\n format = diff < -6 ? 'sameElse' :\n diff < -1 ? 'lastWeek' :\n diff < 0 ? 'lastDay' :\n diff < 1 ? 'sameDay' :\n diff < 2 ? 'nextDay' :\n diff < 7 ? 'nextWeek' : 'sameElse';\n return this.format(formats && formats[format] || this.localeData().calendar(format, this, local__createLocal(now)));\n }\n\n function clone () {\n return new Moment(this);\n }\n\n function isAfter (input, units) {\n var inputMs;\n units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');\n if (units === 'millisecond') {\n input = isMoment(input) ? input : local__createLocal(input);\n return +this > +input;\n } else {\n inputMs = isMoment(input) ? +input : +local__createLocal(input);\n return inputMs < +this.clone().startOf(units);\n }\n }\n\n function isBefore (input, units) {\n var inputMs;\n units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');\n if (units === 'millisecond') {\n input = isMoment(input) ? input : local__createLocal(input);\n return +this < +input;\n } else {\n inputMs = isMoment(input) ? +input : +local__createLocal(input);\n return +this.clone().endOf(units) < inputMs;\n }\n }\n\n function isBetween (from, to, units) {\n return this.isAfter(from, units) && this.isBefore(to, units);\n }\n\n function isSame (input, units) {\n var inputMs;\n units = normalizeUnits(units || 'millisecond');\n if (units === 'millisecond') {\n input = isMoment(input) ? input : local__createLocal(input);\n return +this === +input;\n } else {\n inputMs = +local__createLocal(input);\n return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units));\n }\n }\n\n function diff (input, units, asFloat) {\n var that = cloneWithOffset(input, this),\n zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4,\n delta, output;\n\n units = normalizeUnits(units);\n\n if (units === 'year' || units === 'month' || units === 'quarter') {\n output = monthDiff(this, that);\n if (units === 'quarter') {\n output = output / 3;\n } else if (units === 'year') {\n output = output / 12;\n }\n } else {\n delta = this - that;\n output = units === 'second' ? delta / 1e3 : // 1000\n units === 'minute' ? delta / 6e4 : // 1000 * 60\n units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60\n units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst\n units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst\n delta;\n }\n return asFloat ? output : absFloor(output);\n }\n\n function monthDiff (a, b) {\n // difference in months\n var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),\n // b is in (anchor - 1 month, anchor + 1 month)\n anchor = a.clone().add(wholeMonthDiff, 'months'),\n anchor2, adjust;\n\n if (b - anchor < 0) {\n anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');\n // linear across the month\n adjust = (b - anchor) / (anchor - anchor2);\n } else {\n anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');\n // linear across the month\n adjust = (b - anchor) / (anchor2 - anchor);\n }\n\n return -(wholeMonthDiff + adjust);\n }\n\n utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';\n\n function toString () {\n return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');\n }\n\n function moment_format__toISOString () {\n var m = this.clone().utc();\n if (0 < m.year() && m.year() <= 9999) {\n if ('function' === typeof Date.prototype.toISOString) {\n // native implementation is ~50x faster, use it when we can\n return this.toDate().toISOString();\n } else {\n return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');\n }\n } else {\n return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');\n }\n }\n\n function format (inputString) {\n var output = formatMoment(this, inputString || utils_hooks__hooks.defaultFormat);\n return this.localeData().postformat(output);\n }\n\n function from (time, withoutSuffix) {\n if (!this.isValid()) {\n return this.localeData().invalidDate();\n }\n return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);\n }\n\n function fromNow (withoutSuffix) {\n return this.from(local__createLocal(), withoutSuffix);\n }\n\n function to (time, withoutSuffix) {\n if (!this.isValid()) {\n return this.localeData().invalidDate();\n }\n return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);\n }\n\n function toNow (withoutSuffix) {\n return this.to(local__createLocal(), withoutSuffix);\n }\n\n function locale (key) {\n var newLocaleData;\n\n if (key === undefined) {\n return this._locale._abbr;\n } else {\n newLocaleData = locale_locales__getLocale(key);\n if (newLocaleData != null) {\n this._locale = newLocaleData;\n }\n return this;\n }\n }\n\n var lang = deprecate(\n 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',\n function (key) {\n if (key === undefined) {\n return this.localeData();\n } else {\n return this.locale(key);\n }\n }\n );\n\n function localeData () {\n return this._locale;\n }\n\n function startOf (units) {\n units = normalizeUnits(units);\n // the following switch intentionally omits break keywords\n // to utilize falling through the cases.\n switch (units) {\n case 'year':\n this.month(0);\n /* falls through */\n case 'quarter':\n case 'month':\n this.date(1);\n /* falls through */\n case 'week':\n case 'isoWeek':\n case 'day':\n this.hours(0);\n /* falls through */\n case 'hour':\n this.minutes(0);\n /* falls through */\n case 'minute':\n this.seconds(0);\n /* falls through */\n case 'second':\n this.milliseconds(0);\n }\n\n // weeks are a special case\n if (units === 'week') {\n this.weekday(0);\n }\n if (units === 'isoWeek') {\n this.isoWeekday(1);\n }\n\n // quarters are also special\n if (units === 'quarter') {\n this.month(Math.floor(this.month() / 3) * 3);\n }\n\n return this;\n }\n\n function endOf (units) {\n units = normalizeUnits(units);\n if (units === undefined || units === 'millisecond') {\n return this;\n }\n return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');\n }\n\n function to_type__valueOf () {\n return +this._d - ((this._offset || 0) * 60000);\n }\n\n function unix () {\n return Math.floor(+this / 1000);\n }\n\n function toDate () {\n return this._offset ? new Date(+this) : this._d;\n }\n\n function toArray () {\n var m = this;\n return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];\n }\n\n function toObject () {\n var m = this;\n return {\n years: m.year(),\n months: m.month(),\n date: m.date(),\n hours: m.hours(),\n minutes: m.minutes(),\n seconds: m.seconds(),\n milliseconds: m.milliseconds()\n };\n }\n\n function moment_valid__isValid () {\n return valid__isValid(this);\n }\n\n function parsingFlags () {\n return extend({}, getParsingFlags(this));\n }\n\n function invalidAt () {\n return getParsingFlags(this).overflow;\n }\n\n addFormatToken(0, ['gg', 2], 0, function () {\n return this.weekYear() % 100;\n });\n\n addFormatToken(0, ['GG', 2], 0, function () {\n return this.isoWeekYear() % 100;\n });\n\n function addWeekYearFormatToken (token, getter) {\n addFormatToken(0, [token, token.length], 0, getter);\n }\n\n addWeekYearFormatToken('gggg', 'weekYear');\n addWeekYearFormatToken('ggggg', 'weekYear');\n addWeekYearFormatToken('GGGG', 'isoWeekYear');\n addWeekYearFormatToken('GGGGG', 'isoWeekYear');\n\n // ALIASES\n\n addUnitAlias('weekYear', 'gg');\n addUnitAlias('isoWeekYear', 'GG');\n\n // PARSING\n\n addRegexToken('G', matchSigned);\n addRegexToken('g', matchSigned);\n addRegexToken('GG', match1to2, match2);\n addRegexToken('gg', match1to2, match2);\n addRegexToken('GGGG', match1to4, match4);\n addRegexToken('gggg', match1to4, match4);\n addRegexToken('GGGGG', match1to6, match6);\n addRegexToken('ggggg', match1to6, match6);\n\n addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {\n week[token.substr(0, 2)] = toInt(input);\n });\n\n addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {\n week[token] = utils_hooks__hooks.parseTwoDigitYear(input);\n });\n\n // HELPERS\n\n function weeksInYear(year, dow, doy) {\n return weekOfYear(local__createLocal([year, 11, 31 + dow - doy]), dow, doy).week;\n }\n\n // MOMENTS\n\n function getSetWeekYear (input) {\n var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year;\n return input == null ? year : this.add((input - year), 'y');\n }\n\n function getSetISOWeekYear (input) {\n var year = weekOfYear(this, 1, 4).year;\n return input == null ? year : this.add((input - year), 'y');\n }\n\n function getISOWeeksInYear () {\n return weeksInYear(this.year(), 1, 4);\n }\n\n function getWeeksInYear () {\n var weekInfo = this.localeData()._week;\n return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);\n }\n\n addFormatToken('Q', 0, 0, 'quarter');\n\n // ALIASES\n\n addUnitAlias('quarter', 'Q');\n\n // PARSING\n\n addRegexToken('Q', match1);\n addParseToken('Q', function (input, array) {\n array[MONTH] = (toInt(input) - 1) * 3;\n });\n\n // MOMENTS\n\n function getSetQuarter (input) {\n return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);\n }\n\n addFormatToken('D', ['DD', 2], 'Do', 'date');\n\n // ALIASES\n\n addUnitAlias('date', 'D');\n\n // PARSING\n\n addRegexToken('D', match1to2);\n addRegexToken('DD', match1to2, match2);\n addRegexToken('Do', function (isStrict, locale) {\n return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;\n });\n\n addParseToken(['D', 'DD'], DATE);\n addParseToken('Do', function (input, array) {\n array[DATE] = toInt(input.match(match1to2)[0], 10);\n });\n\n // MOMENTS\n\n var getSetDayOfMonth = makeGetSet('Date', true);\n\n addFormatToken('d', 0, 'do', 'day');\n\n addFormatToken('dd', 0, 0, function (format) {\n return this.localeData().weekdaysMin(this, format);\n });\n\n addFormatToken('ddd', 0, 0, function (format) {\n return this.localeData().weekdaysShort(this, format);\n });\n\n addFormatToken('dddd', 0, 0, function (format) {\n return this.localeData().weekdays(this, format);\n });\n\n addFormatToken('e', 0, 0, 'weekday');\n addFormatToken('E', 0, 0, 'isoWeekday');\n\n // ALIASES\n\n addUnitAlias('day', 'd');\n addUnitAlias('weekday', 'e');\n addUnitAlias('isoWeekday', 'E');\n\n // PARSING\n\n addRegexToken('d', match1to2);\n addRegexToken('e', match1to2);\n addRegexToken('E', match1to2);\n addRegexToken('dd', matchWord);\n addRegexToken('ddd', matchWord);\n addRegexToken('dddd', matchWord);\n\n addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config) {\n var weekday = config._locale.weekdaysParse(input);\n // if we didn't get a weekday name, mark the date as invalid\n if (weekday != null) {\n week.d = weekday;\n } else {\n getParsingFlags(config).invalidWeekday = input;\n }\n });\n\n addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {\n week[token] = toInt(input);\n });\n\n // HELPERS\n\n function parseWeekday(input, locale) {\n if (typeof input !== 'string') {\n return input;\n }\n\n if (!isNaN(input)) {\n return parseInt(input, 10);\n }\n\n input = locale.weekdaysParse(input);\n if (typeof input === 'number') {\n return input;\n }\n\n return null;\n }\n\n // LOCALES\n\n var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');\n function localeWeekdays (m) {\n return this._weekdays[m.day()];\n }\n\n var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');\n function localeWeekdaysShort (m) {\n return this._weekdaysShort[m.day()];\n }\n\n var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');\n function localeWeekdaysMin (m) {\n return this._weekdaysMin[m.day()];\n }\n\n function localeWeekdaysParse (weekdayName) {\n var i, mom, regex;\n\n this._weekdaysParse = this._weekdaysParse || [];\n\n for (i = 0; i < 7; i++) {\n // make the regex if we don't have it already\n if (!this._weekdaysParse[i]) {\n mom = local__createLocal([2000, 1]).day(i);\n regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');\n this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');\n }\n // test the regex\n if (this._weekdaysParse[i].test(weekdayName)) {\n return i;\n }\n }\n }\n\n // MOMENTS\n\n function getSetDayOfWeek (input) {\n var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();\n if (input != null) {\n input = parseWeekday(input, this.localeData());\n return this.add(input - day, 'd');\n } else {\n return day;\n }\n }\n\n function getSetLocaleDayOfWeek (input) {\n var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;\n return input == null ? weekday : this.add(input - weekday, 'd');\n }\n\n function getSetISODayOfWeek (input) {\n // behaves the same as moment#day except\n // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)\n // as a setter, sunday should belong to the previous week.\n return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);\n }\n\n addFormatToken('H', ['HH', 2], 0, 'hour');\n addFormatToken('h', ['hh', 2], 0, function () {\n return this.hours() % 12 || 12;\n });\n\n function meridiem (token, lowercase) {\n addFormatToken(token, 0, 0, function () {\n return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);\n });\n }\n\n meridiem('a', true);\n meridiem('A', false);\n\n // ALIASES\n\n addUnitAlias('hour', 'h');\n\n // PARSING\n\n function matchMeridiem (isStrict, locale) {\n return locale._meridiemParse;\n }\n\n addRegexToken('a', matchMeridiem);\n addRegexToken('A', matchMeridiem);\n addRegexToken('H', match1to2);\n addRegexToken('h', match1to2);\n addRegexToken('HH', match1to2, match2);\n addRegexToken('hh', match1to2, match2);\n\n addParseToken(['H', 'HH'], HOUR);\n addParseToken(['a', 'A'], function (input, array, config) {\n config._isPm = config._locale.isPM(input);\n config._meridiem = input;\n });\n addParseToken(['h', 'hh'], function (input, array, config) {\n array[HOUR] = toInt(input);\n getParsingFlags(config).bigHour = true;\n });\n\n // LOCALES\n\n function localeIsPM (input) {\n // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays\n // Using charAt should be more compatible.\n return ((input + '').toLowerCase().charAt(0) === 'p');\n }\n\n var defaultLocaleMeridiemParse = /[ap]\\.?m?\\.?/i;\n function localeMeridiem (hours, minutes, isLower) {\n if (hours > 11) {\n return isLower ? 'pm' : 'PM';\n } else {\n return isLower ? 'am' : 'AM';\n }\n }\n\n\n // MOMENTS\n\n // Setting the hour should keep the time, because the user explicitly\n // specified which hour he wants. So trying to maintain the same hour (in\n // a new timezone) makes sense. Adding/subtracting hours does not follow\n // this rule.\n var getSetHour = makeGetSet('Hours', true);\n\n addFormatToken('m', ['mm', 2], 0, 'minute');\n\n // ALIASES\n\n addUnitAlias('minute', 'm');\n\n // PARSING\n\n addRegexToken('m', match1to2);\n addRegexToken('mm', match1to2, match2);\n addParseToken(['m', 'mm'], MINUTE);\n\n // MOMENTS\n\n var getSetMinute = makeGetSet('Minutes', false);\n\n addFormatToken('s', ['ss', 2], 0, 'second');\n\n // ALIASES\n\n addUnitAlias('second', 's');\n\n // PARSING\n\n addRegexToken('s', match1to2);\n addRegexToken('ss', match1to2, match2);\n addParseToken(['s', 'ss'], SECOND);\n\n // MOMENTS\n\n var getSetSecond = makeGetSet('Seconds', false);\n\n addFormatToken('S', 0, 0, function () {\n return ~~(this.millisecond() / 100);\n });\n\n addFormatToken(0, ['SS', 2], 0, function () {\n return ~~(this.millisecond() / 10);\n });\n\n addFormatToken(0, ['SSS', 3], 0, 'millisecond');\n addFormatToken(0, ['SSSS', 4], 0, function () {\n return this.millisecond() * 10;\n });\n addFormatToken(0, ['SSSSS', 5], 0, function () {\n return this.millisecond() * 100;\n });\n addFormatToken(0, ['SSSSSS', 6], 0, function () {\n return this.millisecond() * 1000;\n });\n addFormatToken(0, ['SSSSSSS', 7], 0, function () {\n return this.millisecond() * 10000;\n });\n addFormatToken(0, ['SSSSSSSS', 8], 0, function () {\n return this.millisecond() * 100000;\n });\n addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {\n return this.millisecond() * 1000000;\n });\n\n\n // ALIASES\n\n addUnitAlias('millisecond', 'ms');\n\n // PARSING\n\n addRegexToken('S', match1to3, match1);\n addRegexToken('SS', match1to3, match2);\n addRegexToken('SSS', match1to3, match3);\n\n var token;\n for (token = 'SSSS'; token.length <= 9; token += 'S') {\n addRegexToken(token, matchUnsigned);\n }\n\n function parseMs(input, array) {\n array[MILLISECOND] = toInt(('0.' + input) * 1000);\n }\n\n for (token = 'S'; token.length <= 9; token += 'S') {\n addParseToken(token, parseMs);\n }\n // MOMENTS\n\n var getSetMillisecond = makeGetSet('Milliseconds', false);\n\n addFormatToken('z', 0, 0, 'zoneAbbr');\n addFormatToken('zz', 0, 0, 'zoneName');\n\n // MOMENTS\n\n function getZoneAbbr () {\n return this._isUTC ? 'UTC' : '';\n }\n\n function getZoneName () {\n return this._isUTC ? 'Coordinated Universal Time' : '';\n }\n\n var momentPrototype__proto = Moment.prototype;\n\n momentPrototype__proto.add = add_subtract__add;\n momentPrototype__proto.calendar = moment_calendar__calendar;\n momentPrototype__proto.clone = clone;\n momentPrototype__proto.diff = diff;\n momentPrototype__proto.endOf = endOf;\n momentPrototype__proto.format = format;\n momentPrototype__proto.from = from;\n momentPrototype__proto.fromNow = fromNow;\n momentPrototype__proto.to = to;\n momentPrototype__proto.toNow = toNow;\n momentPrototype__proto.get = getSet;\n momentPrototype__proto.invalidAt = invalidAt;\n momentPrototype__proto.isAfter = isAfter;\n momentPrototype__proto.isBefore = isBefore;\n momentPrototype__proto.isBetween = isBetween;\n momentPrototype__proto.isSame = isSame;\n momentPrototype__proto.isValid = moment_valid__isValid;\n momentPrototype__proto.lang = lang;\n momentPrototype__proto.locale = locale;\n momentPrototype__proto.localeData = localeData;\n momentPrototype__proto.max = prototypeMax;\n momentPrototype__proto.min = prototypeMin;\n momentPrototype__proto.parsingFlags = parsingFlags;\n momentPrototype__proto.set = getSet;\n momentPrototype__proto.startOf = startOf;\n momentPrototype__proto.subtract = add_subtract__subtract;\n momentPrototype__proto.toArray = toArray;\n momentPrototype__proto.toObject = toObject;\n momentPrototype__proto.toDate = toDate;\n momentPrototype__proto.toISOString = moment_format__toISOString;\n momentPrototype__proto.toJSON = moment_format__toISOString;\n momentPrototype__proto.toString = toString;\n momentPrototype__proto.unix = unix;\n momentPrototype__proto.valueOf = to_type__valueOf;\n\n // Year\n momentPrototype__proto.year = getSetYear;\n momentPrototype__proto.isLeapYear = getIsLeapYear;\n\n // Week Year\n momentPrototype__proto.weekYear = getSetWeekYear;\n momentPrototype__proto.isoWeekYear = getSetISOWeekYear;\n\n // Quarter\n momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter;\n\n // Month\n momentPrototype__proto.month = getSetMonth;\n momentPrototype__proto.daysInMonth = getDaysInMonth;\n\n // Week\n momentPrototype__proto.week = momentPrototype__proto.weeks = getSetWeek;\n momentPrototype__proto.isoWeek = momentPrototype__proto.isoWeeks = getSetISOWeek;\n momentPrototype__proto.weeksInYear = getWeeksInYear;\n momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear;\n\n // Day\n momentPrototype__proto.date = getSetDayOfMonth;\n momentPrototype__proto.day = momentPrototype__proto.days = getSetDayOfWeek;\n momentPrototype__proto.weekday = getSetLocaleDayOfWeek;\n momentPrototype__proto.isoWeekday = getSetISODayOfWeek;\n momentPrototype__proto.dayOfYear = getSetDayOfYear;\n\n // Hour\n momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour;\n\n // Minute\n momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute;\n\n // Second\n momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond;\n\n // Millisecond\n momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond;\n\n // Offset\n momentPrototype__proto.utcOffset = getSetOffset;\n momentPrototype__proto.utc = setOffsetToUTC;\n momentPrototype__proto.local = setOffsetToLocal;\n momentPrototype__proto.parseZone = setOffsetToParsedOffset;\n momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;\n momentPrototype__proto.isDST = isDaylightSavingTime;\n momentPrototype__proto.isDSTShifted = isDaylightSavingTimeShifted;\n momentPrototype__proto.isLocal = isLocal;\n momentPrototype__proto.isUtcOffset = isUtcOffset;\n momentPrototype__proto.isUtc = isUtc;\n momentPrototype__proto.isUTC = isUtc;\n\n // Timezone\n momentPrototype__proto.zoneAbbr = getZoneAbbr;\n momentPrototype__proto.zoneName = getZoneName;\n\n // Deprecations\n momentPrototype__proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);\n momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);\n momentPrototype__proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);\n momentPrototype__proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone);\n\n var momentPrototype = momentPrototype__proto;\n\n function moment__createUnix (input) {\n return local__createLocal(input * 1000);\n }\n\n function moment__createInZone () {\n return local__createLocal.apply(null, arguments).parseZone();\n }\n\n var defaultCalendar = {\n sameDay : '[Today at] LT',\n nextDay : '[Tomorrow at] LT',\n nextWeek : 'dddd [at] LT',\n lastDay : '[Yesterday at] LT',\n lastWeek : '[Last] dddd [at] LT',\n sameElse : 'L'\n };\n\n function locale_calendar__calendar (key, mom, now) {\n var output = this._calendar[key];\n return typeof output === 'function' ? output.call(mom, now) : output;\n }\n\n var defaultLongDateFormat = {\n LTS : 'h:mm:ss A',\n LT : 'h:mm A',\n L : 'MM/DD/YYYY',\n LL : 'MMMM D, YYYY',\n LLL : 'MMMM D, YYYY h:mm A',\n LLLL : 'dddd, MMMM D, YYYY h:mm A'\n };\n\n function longDateFormat (key) {\n var format = this._longDateFormat[key],\n formatUpper = this._longDateFormat[key.toUpperCase()];\n\n if (format || !formatUpper) {\n return format;\n }\n\n this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {\n return val.slice(1);\n });\n\n return this._longDateFormat[key];\n }\n\n var defaultInvalidDate = 'Invalid date';\n\n function invalidDate () {\n return this._invalidDate;\n }\n\n var defaultOrdinal = '%d';\n var defaultOrdinalParse = /\\d{1,2}/;\n\n function ordinal (number) {\n return this._ordinal.replace('%d', number);\n }\n\n function preParsePostFormat (string) {\n return string;\n }\n\n var defaultRelativeTime = {\n future : 'in %s',\n past : '%s ago',\n s : 'a few seconds',\n m : 'a minute',\n mm : '%d minutes',\n h : 'an hour',\n hh : '%d hours',\n d : 'a day',\n dd : '%d days',\n M : 'a month',\n MM : '%d months',\n y : 'a year',\n yy : '%d years'\n };\n\n function relative__relativeTime (number, withoutSuffix, string, isFuture) {\n var output = this._relativeTime[string];\n return (typeof output === 'function') ?\n output(number, withoutSuffix, string, isFuture) :\n output.replace(/%d/i, number);\n }\n\n function pastFuture (diff, output) {\n var format = this._relativeTime[diff > 0 ? 'future' : 'past'];\n return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);\n }\n\n function locale_set__set (config) {\n var prop, i;\n for (i in config) {\n prop = config[i];\n if (typeof prop === 'function') {\n this[i] = prop;\n } else {\n this['_' + i] = prop;\n }\n }\n // Lenient ordinal parsing accepts just a number in addition to\n // number + (possibly) stuff coming from _ordinalParseLenient.\n this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\\d{1,2}/).source);\n }\n\n var prototype__proto = Locale.prototype;\n\n prototype__proto._calendar = defaultCalendar;\n prototype__proto.calendar = locale_calendar__calendar;\n prototype__proto._longDateFormat = defaultLongDateFormat;\n prototype__proto.longDateFormat = longDateFormat;\n prototype__proto._invalidDate = defaultInvalidDate;\n prototype__proto.invalidDate = invalidDate;\n prototype__proto._ordinal = defaultOrdinal;\n prototype__proto.ordinal = ordinal;\n prototype__proto._ordinalParse = defaultOrdinalParse;\n prototype__proto.preparse = preParsePostFormat;\n prototype__proto.postformat = preParsePostFormat;\n prototype__proto._relativeTime = defaultRelativeTime;\n prototype__proto.relativeTime = relative__relativeTime;\n prototype__proto.pastFuture = pastFuture;\n prototype__proto.set = locale_set__set;\n\n // Month\n prototype__proto.months = localeMonths;\n prototype__proto._months = defaultLocaleMonths;\n prototype__proto.monthsShort = localeMonthsShort;\n prototype__proto._monthsShort = defaultLocaleMonthsShort;\n prototype__proto.monthsParse = localeMonthsParse;\n\n // Week\n prototype__proto.week = localeWeek;\n prototype__proto._week = defaultLocaleWeek;\n prototype__proto.firstDayOfYear = localeFirstDayOfYear;\n prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;\n\n // Day of Week\n prototype__proto.weekdays = localeWeekdays;\n prototype__proto._weekdays = defaultLocaleWeekdays;\n prototype__proto.weekdaysMin = localeWeekdaysMin;\n prototype__proto._weekdaysMin = defaultLocaleWeekdaysMin;\n prototype__proto.weekdaysShort = localeWeekdaysShort;\n prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort;\n prototype__proto.weekdaysParse = localeWeekdaysParse;\n\n // Hours\n prototype__proto.isPM = localeIsPM;\n prototype__proto._meridiemParse = defaultLocaleMeridiemParse;\n prototype__proto.meridiem = localeMeridiem;\n\n function lists__get (format, index, field, setter) {\n var locale = locale_locales__getLocale();\n var utc = create_utc__createUTC().set(setter, index);\n return locale[field](utc, format);\n }\n\n function list (format, index, field, count, setter) {\n if (typeof format === 'number') {\n index = format;\n format = undefined;\n }\n\n format = format || '';\n\n if (index != null) {\n return lists__get(format, index, field, setter);\n }\n\n var i;\n var out = [];\n for (i = 0; i < count; i++) {\n out[i] = lists__get(format, i, field, setter);\n }\n return out;\n }\n\n function lists__listMonths (format, index) {\n return list(format, index, 'months', 12, 'month');\n }\n\n function lists__listMonthsShort (format, index) {\n return list(format, index, 'monthsShort', 12, 'month');\n }\n\n function lists__listWeekdays (format, index) {\n return list(format, index, 'weekdays', 7, 'day');\n }\n\n function lists__listWeekdaysShort (format, index) {\n return list(format, index, 'weekdaysShort', 7, 'day');\n }\n\n function lists__listWeekdaysMin (format, index) {\n return list(format, index, 'weekdaysMin', 7, 'day');\n }\n\n locale_locales__getSetGlobalLocale('en', {\n ordinalParse: /\\d{1,2}(th|st|nd|rd)/,\n ordinal : function (number) {\n var b = number % 10,\n output = (toInt(number % 100 / 10) === 1) ? 'th' :\n (b === 1) ? 'st' :\n (b === 2) ? 'nd' :\n (b === 3) ? 'rd' : 'th';\n return number + output;\n }\n });\n\n // Side effect imports\n utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale);\n utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale);\n\n var mathAbs = Math.abs;\n\n function duration_abs__abs () {\n var data = this._data;\n\n this._milliseconds = mathAbs(this._milliseconds);\n this._days = mathAbs(this._days);\n this._months = mathAbs(this._months);\n\n data.milliseconds = mathAbs(data.milliseconds);\n data.seconds = mathAbs(data.seconds);\n data.minutes = mathAbs(data.minutes);\n data.hours = mathAbs(data.hours);\n data.months = mathAbs(data.months);\n data.years = mathAbs(data.years);\n\n return this;\n }\n\n function duration_add_subtract__addSubtract (duration, input, value, direction) {\n var other = create__createDuration(input, value);\n\n duration._milliseconds += direction * other._milliseconds;\n duration._days += direction * other._days;\n duration._months += direction * other._months;\n\n return duration._bubble();\n }\n\n // supports only 2.0-style add(1, 's') or add(duration)\n function duration_add_subtract__add (input, value) {\n return duration_add_subtract__addSubtract(this, input, value, 1);\n }\n\n // supports only 2.0-style subtract(1, 's') or subtract(duration)\n function duration_add_subtract__subtract (input, value) {\n return duration_add_subtract__addSubtract(this, input, value, -1);\n }\n\n function absCeil (number) {\n if (number < 0) {\n return Math.floor(number);\n } else {\n return Math.ceil(number);\n }\n }\n\n function bubble () {\n var milliseconds = this._milliseconds;\n var days = this._days;\n var months = this._months;\n var data = this._data;\n var seconds, minutes, hours, years, monthsFromDays;\n\n // if we have a mix of positive and negative values, bubble down first\n // check: https://github.com/moment/moment/issues/2166\n if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||\n (milliseconds <= 0 && days <= 0 && months <= 0))) {\n milliseconds += absCeil(monthsToDays(months) + days) * 864e5;\n days = 0;\n months = 0;\n }\n\n // The following code bubbles up values, see the tests for\n // examples of what that means.\n data.milliseconds = milliseconds % 1000;\n\n seconds = absFloor(milliseconds / 1000);\n data.seconds = seconds % 60;\n\n minutes = absFloor(seconds / 60);\n data.minutes = minutes % 60;\n\n hours = absFloor(minutes / 60);\n data.hours = hours % 24;\n\n days += absFloor(hours / 24);\n\n // convert days to months\n monthsFromDays = absFloor(daysToMonths(days));\n months += monthsFromDays;\n days -= absCeil(monthsToDays(monthsFromDays));\n\n // 12 months -> 1 year\n years = absFloor(months / 12);\n months %= 12;\n\n data.days = days;\n data.months = months;\n data.years = years;\n\n return this;\n }\n\n function daysToMonths (days) {\n // 400 years have 146097 days (taking into account leap year rules)\n // 400 years have 12 months === 4800\n return days * 4800 / 146097;\n }\n\n function monthsToDays (months) {\n // the reverse of daysToMonths\n return months * 146097 / 4800;\n }\n\n function as (units) {\n var days;\n var months;\n var milliseconds = this._milliseconds;\n\n units = normalizeUnits(units);\n\n if (units === 'month' || units === 'year') {\n days = this._days + milliseconds / 864e5;\n months = this._months + daysToMonths(days);\n return units === 'month' ? months : months / 12;\n } else {\n // handle milliseconds separately because of floating point math errors (issue #1867)\n days = this._days + Math.round(monthsToDays(this._months));\n switch (units) {\n case 'week' : return days / 7 + milliseconds / 6048e5;\n case 'day' : return days + milliseconds / 864e5;\n case 'hour' : return days * 24 + milliseconds / 36e5;\n case 'minute' : return days * 1440 + milliseconds / 6e4;\n case 'second' : return days * 86400 + milliseconds / 1000;\n // Math.floor prevents floating point math errors here\n case 'millisecond': return Math.floor(days * 864e5) + milliseconds;\n default: throw new Error('Unknown unit ' + units);\n }\n }\n }\n\n // TODO: Use this.as('ms')?\n function duration_as__valueOf () {\n return (\n this._milliseconds +\n this._days * 864e5 +\n (this._months % 12) * 2592e6 +\n toInt(this._months / 12) * 31536e6\n );\n }\n\n function makeAs (alias) {\n return function () {\n return this.as(alias);\n };\n }\n\n var asMilliseconds = makeAs('ms');\n var asSeconds = makeAs('s');\n var asMinutes = makeAs('m');\n var asHours = makeAs('h');\n var asDays = makeAs('d');\n var asWeeks = makeAs('w');\n var asMonths = makeAs('M');\n var asYears = makeAs('y');\n\n function duration_get__get (units) {\n units = normalizeUnits(units);\n return this[units + 's']();\n }\n\n function makeGetter(name) {\n return function () {\n return this._data[name];\n };\n }\n\n var milliseconds = makeGetter('milliseconds');\n var seconds = makeGetter('seconds');\n var minutes = makeGetter('minutes');\n var hours = makeGetter('hours');\n var days = makeGetter('days');\n var months = makeGetter('months');\n var years = makeGetter('years');\n\n function weeks () {\n return absFloor(this.days() / 7);\n }\n\n var round = Math.round;\n var thresholds = {\n s: 45, // seconds to minute\n m: 45, // minutes to hour\n h: 22, // hours to day\n d: 26, // days to month\n M: 11 // months to year\n };\n\n // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize\n function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {\n return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);\n }\n\n function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) {\n var duration = create__createDuration(posNegDuration).abs();\n var seconds = round(duration.as('s'));\n var minutes = round(duration.as('m'));\n var hours = round(duration.as('h'));\n var days = round(duration.as('d'));\n var months = round(duration.as('M'));\n var years = round(duration.as('y'));\n\n var a = seconds < thresholds.s && ['s', seconds] ||\n minutes === 1 && ['m'] ||\n minutes < thresholds.m && ['mm', minutes] ||\n hours === 1 && ['h'] ||\n hours < thresholds.h && ['hh', hours] ||\n days === 1 && ['d'] ||\n days < thresholds.d && ['dd', days] ||\n months === 1 && ['M'] ||\n months < thresholds.M && ['MM', months] ||\n years === 1 && ['y'] || ['yy', years];\n\n a[2] = withoutSuffix;\n a[3] = +posNegDuration > 0;\n a[4] = locale;\n return substituteTimeAgo.apply(null, a);\n }\n\n // This function allows you to set a threshold for relative time strings\n function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) {\n if (thresholds[threshold] === undefined) {\n return false;\n }\n if (limit === undefined) {\n return thresholds[threshold];\n }\n thresholds[threshold] = limit;\n return true;\n }\n\n function humanize (withSuffix) {\n var locale = this.localeData();\n var output = duration_humanize__relativeTime(this, !withSuffix, locale);\n\n if (withSuffix) {\n output = locale.pastFuture(+this, output);\n }\n\n return locale.postformat(output);\n }\n\n var iso_string__abs = Math.abs;\n\n function iso_string__toISOString() {\n // for ISO strings we do not use the normal bubbling rules:\n // * milliseconds bubble up until they become hours\n // * days do not bubble at all\n // * months bubble up until they become years\n // This is because there is no context-free conversion between hours and days\n // (think of clock changes)\n // and also not between days and months (28-31 days per month)\n var seconds = iso_string__abs(this._milliseconds) / 1000;\n var days = iso_string__abs(this._days);\n var months = iso_string__abs(this._months);\n var minutes, hours, years;\n\n // 3600 seconds -> 60 minutes -> 1 hour\n minutes = absFloor(seconds / 60);\n hours = absFloor(minutes / 60);\n seconds %= 60;\n minutes %= 60;\n\n // 12 months -> 1 year\n years = absFloor(months / 12);\n months %= 12;\n\n\n // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js\n var Y = years;\n var M = months;\n var D = days;\n var h = hours;\n var m = minutes;\n var s = seconds;\n var total = this.asSeconds();\n\n if (!total) {\n // this is the same as C#'s (Noda) and python (isodate)...\n // but not other JS (goog.date)\n return 'P0D';\n }\n\n return (total < 0 ? '-' : '') +\n 'P' +\n (Y ? Y + 'Y' : '') +\n (M ? M + 'M' : '') +\n (D ? D + 'D' : '') +\n ((h || m || s) ? 'T' : '') +\n (h ? h + 'H' : '') +\n (m ? m + 'M' : '') +\n (s ? s + 'S' : '');\n }\n\n var duration_prototype__proto = Duration.prototype;\n\n duration_prototype__proto.abs = duration_abs__abs;\n duration_prototype__proto.add = duration_add_subtract__add;\n duration_prototype__proto.subtract = duration_add_subtract__subtract;\n duration_prototype__proto.as = as;\n duration_prototype__proto.asMilliseconds = asMilliseconds;\n duration_prototype__proto.asSeconds = asSeconds;\n duration_prototype__proto.asMinutes = asMinutes;\n duration_prototype__proto.asHours = asHours;\n duration_prototype__proto.asDays = asDays;\n duration_prototype__proto.asWeeks = asWeeks;\n duration_prototype__proto.asMonths = asMonths;\n duration_prototype__proto.asYears = asYears;\n duration_prototype__proto.valueOf = duration_as__valueOf;\n duration_prototype__proto._bubble = bubble;\n duration_prototype__proto.get = duration_get__get;\n duration_prototype__proto.milliseconds = milliseconds;\n duration_prototype__proto.seconds = seconds;\n duration_prototype__proto.minutes = minutes;\n duration_prototype__proto.hours = hours;\n duration_prototype__proto.days = days;\n duration_prototype__proto.weeks = weeks;\n duration_prototype__proto.months = months;\n duration_prototype__proto.years = years;\n duration_prototype__proto.humanize = humanize;\n duration_prototype__proto.toISOString = iso_string__toISOString;\n duration_prototype__proto.toString = iso_string__toISOString;\n duration_prototype__proto.toJSON = iso_string__toISOString;\n duration_prototype__proto.locale = locale;\n duration_prototype__proto.localeData = localeData;\n\n // Deprecations\n duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString);\n duration_prototype__proto.lang = lang;\n\n // Side effect imports\n\n addFormatToken('X', 0, 0, 'unix');\n addFormatToken('x', 0, 0, 'valueOf');\n\n // PARSING\n\n addRegexToken('x', matchSigned);\n addRegexToken('X', matchTimestamp);\n addParseToken('X', function (input, array, config) {\n config._d = new Date(parseFloat(input, 10) * 1000);\n });\n addParseToken('x', function (input, array, config) {\n config._d = new Date(toInt(input));\n });\n\n // Side effect imports\n\n\n utils_hooks__hooks.version = '2.10.6';\n\n setHookCallback(local__createLocal);\n\n utils_hooks__hooks.fn = momentPrototype;\n utils_hooks__hooks.min = min;\n utils_hooks__hooks.max = max;\n utils_hooks__hooks.utc = create_utc__createUTC;\n utils_hooks__hooks.unix = moment__createUnix;\n utils_hooks__hooks.months = lists__listMonths;\n utils_hooks__hooks.isDate = isDate;\n utils_hooks__hooks.locale = locale_locales__getSetGlobalLocale;\n utils_hooks__hooks.invalid = valid__createInvalid;\n utils_hooks__hooks.duration = create__createDuration;\n utils_hooks__hooks.isMoment = isMoment;\n utils_hooks__hooks.weekdays = lists__listWeekdays;\n utils_hooks__hooks.parseZone = moment__createInZone;\n utils_hooks__hooks.localeData = locale_locales__getLocale;\n utils_hooks__hooks.isDuration = isDuration;\n utils_hooks__hooks.monthsShort = lists__listMonthsShort;\n utils_hooks__hooks.weekdaysMin = lists__listWeekdaysMin;\n utils_hooks__hooks.defineLocale = defineLocale;\n utils_hooks__hooks.weekdaysShort = lists__listWeekdaysShort;\n utils_hooks__hooks.normalizeUnits = normalizeUnits;\n utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold;\n\n var _moment = utils_hooks__hooks;\n\n return _moment;\n\n}));\n/*****************************************************************************\\\n\n Javascript \"SOAP Client\" library\n \n @version: 2.4 - 2007.12.21\n @author: Matteo Casati - http://www.guru4.net/\n \n\\*****************************************************************************/\n\nfunction SOAPClientParameters()\n{\n\tvar _pl = new Array();\n\tthis.add = function(name, value) \n\t{\n\t\t_pl[name] = value; \n\t\treturn this; \n\t}\n\tthis.toXml = function()\n\t{\n\t\tvar xml = \"\";\n\t\tfor(var p in _pl)\n\t\t{\n\t\t\tswitch(typeof(_pl[p])) \n\t\t\t{\n case \"string\":\n case \"number\":\n case \"boolean\":\n case \"object\":\n xml += \"<\" + p + \">\" + SOAPClientParameters._serialize(_pl[p]) + \"\" + p + \">\";\n break;\n default:\n break;\n }\n\t\t}\n\t\treturn xml;\t\n\t}\n}\nSOAPClientParameters._serialize = function(o)\n{\n var s = \"\";\n switch(typeof(o))\n {\n case \"string\":\n s += o.replace(/&/g, \"&\").replace(//g, \">\"); break;\n case \"number\":\n case \"boolean\":\n s += o.toString(); break;\n case \"object\":\n // Date\n if(o.constructor.toString().indexOf(\"function Date()\") > -1)\n {\n \n var year = o.getFullYear().toString();\n var month = (o.getMonth() + 1).toString(); month = (month.length == 1) ? \"0\" + month : month;\n var date = o.getDate().toString(); date = (date.length == 1) ? \"0\" + date : date;\n var hours = o.getHours().toString(); hours = (hours.length == 1) ? \"0\" + hours : hours;\n var minutes = o.getMinutes().toString(); minutes = (minutes.length == 1) ? \"0\" + minutes : minutes;\n var seconds = o.getSeconds().toString(); seconds = (seconds.length == 1) ? \"0\" + seconds : seconds;\n var milliseconds = o.getMilliseconds().toString();\n var tzminutes = Math.abs(o.getTimezoneOffset());\n var tzhours = 0;\n while(tzminutes >= 60)\n {\n tzhours++;\n tzminutes -= 60;\n }\n tzminutes = (tzminutes.toString().length == 1) ? \"0\" + tzminutes.toString() : tzminutes.toString();\n tzhours = (tzhours.toString().length == 1) ? \"0\" + tzhours.toString() : tzhours.toString();\n var timezone = ((o.getTimezoneOffset() < 0) ? \"+\" : \"-\") + tzhours + \":\" + tzminutes;\n s += year + \"-\" + month + \"-\" + date + \"T\" + hours + \":\" + minutes + \":\" + seconds + \".\" + milliseconds + timezone;\n }\n // Array\n else if(o.constructor.toString().indexOf(\"function Array()\") > -1)\n {\n for(var p in o)\n {\n if(!isNaN(p)) // linear array\n {\n (/function\\s+(\\w*)\\s*\\(/ig).exec(o[p].constructor.toString());\n var type = RegExp.$1;\n switch(type)\n {\n case \"\":\n type = typeof(o[p]);\n case \"String\":\n type = \"string\"; break;\n case \"Number\":\n type = \"int\"; break;\n case \"Boolean\":\n type = \"bool\"; break;\n case \"Date\":\n type = \"DateTime\"; break;\n }\n s += \"<\" + type + \">\" + SOAPClientParameters._serialize(o[p]) + \"\" + type + \">\"\n }\n else // associative array\n s += \"<\" + p + \">\" + SOAPClientParameters._serialize(o[p]) + \"\" + p + \">\"\n }\n }\n // Object or custom function\n else\n for(var p in o)\n s += \"<\" + p + \">\" + SOAPClientParameters._serialize(o[p]) + \"\" + p + \">\";\n break;\n default:\n break; // throw new Error(500, \"SOAPClientParameters: type '\" + typeof(o) + \"' is not supported\");\n }\n return s;\n}\n\nfunction SOAPClient() {}\n\nSOAPClient.username = null;\nSOAPClient.password = null;\n\nSOAPClient.invoke = function(url, method, parameters, async, callback)\n{\n\tif(async)\n\t\tSOAPClient._loadWsdl(url, method, parameters, async, callback);\n\telse\n\t\treturn SOAPClient._loadWsdl(url, method, parameters, async, callback);\n}\n\n// private: wsdl cache\nSOAPClient_cacheWsdl = new Array();\n\n// private: invoke async\nSOAPClient._loadWsdl = function(url, method, parameters, async, callback)\n{\n\t// load from cache?\n\tvar wsdl = SOAPClient_cacheWsdl[url];\n\tif(wsdl + \"\" != \"\" && wsdl + \"\" != \"undefined\")\n\t\treturn SOAPClient._sendSoapRequest(url, method, parameters, async, callback, wsdl);\n\t// get wsdl\n\tvar xmlHttp = SOAPClient._getXmlHttp();\n\tif (SOAPClient.username && SOAPClient.password){\n\t\txmlHttp.open(\"GET\", url + \"?wsdl\", async, SOAPClient.username, SOAPClient.password);\n\t\t// Some WS implementations (i.e. BEA WebLogic Server 10.0 JAX-WS) don't support Challenge/Response HTTP BASIC, so we send authorization headers in the first request\n\t\txmlHttp.setRequestHeader(\"Authorization\", \"Basic \" + SOAPClient._toBase64(SOAPClient.username + \":\" + SOAPClient.password));\n\t}\n\telse\n\t\txmlHttp.open(\"GET\", url + \"?wsdl\", async);\n\tif(async) \n\t{\n\t\txmlHttp.onreadystatechange = function() \n\t\t{\n\t\t\tif(xmlHttp.readyState == 4)\n\t\t\t\tSOAPClient._onLoadWsdl(url, method, parameters, async, callback, xmlHttp);\n\t\t}\n\t}\n\txmlHttp.send(null);\n\tif (!async)\n\t\treturn SOAPClient._onLoadWsdl(url, method, parameters, async, callback, xmlHttp);\n}\nSOAPClient._onLoadWsdl = function(url, method, parameters, async, callback, req)\n{\n\tvar wsdl = req.responseXML;\n\tSOAPClient_cacheWsdl[url] = wsdl;\t// save a copy in cache\n\treturn SOAPClient._sendSoapRequest(url, method, parameters, async, callback, wsdl);\n}\nSOAPClient._sendSoapRequest = function(url, method, parameters, async, callback, wsdl)\n{\n\t// get namespace\n\tvar ns = (wsdl.documentElement.attributes[\"targetNamespace\"] + \"\" == \"undefined\") ? wsdl.documentElement.attributes.getNamedItem(\"targetNamespace\").nodeValue : wsdl.documentElement.attributes[\"targetNamespace\"].value;\n\t// build SOAP request\n\tvar sr = \n\t\t\t\t\"\" +\n\t\t\t\t\"
\" +\n\t\t\t\t\"\" +\n\t\t\t\t\"<\" + method + \" xmlns=\\\"\" + ns + \"\\\">\" +\n\t\t\t\tparameters.toXml() +\n\t\t\t\t\"\" + method + \">\";\n\t// send request\n\tvar xmlHttp = SOAPClient._getXmlHttp();\n\tif (SOAPClient.username && SOAPClient.password){\n\t\txmlHttp.open(\"POST\", url, async, SOAPClient.username, SOAPClient.password);\n\t\t// Some WS implementations (i.e. BEA WebLogic Server 10.0 JAX-WS) don't support Challenge/Response HTTP BASIC, so we send authorization headers in the first request\n\t\txmlHttp.setRequestHeader(\"Authorization\", \"Basic \" + SOAPClient._toBase64(SOAPClient.username + \":\" + SOAPClient.password));\n\t}\n\telse\n\t\txmlHttp.open(\"POST\", url, async);\n\tvar soapaction = ((ns.lastIndexOf(\"/\") != ns.length - 1) ? ns + \"/\" : ns) + encodeURIComponent(method);\n\txmlHttp.setRequestHeader(\"SOAPAction\", soapaction);\n\txmlHttp.setRequestHeader(\"Content-Type\", \"text/xml; charset=utf-8\");\n\tif(async) \n\t{\n\t\txmlHttp.onreadystatechange = function() \n\t\t{\n\t\t\tif(xmlHttp.readyState == 4)\n\t\t\t\tSOAPClient._onSendSoapRequest(method, async, callback, wsdl, xmlHttp);\n\t\t}\n\t}\n\txmlHttp.send(sr);\n\tif (!async)\n\t\treturn SOAPClient._onSendSoapRequest(method, async, callback, wsdl, xmlHttp);\n}\n\nSOAPClient._onSendSoapRequest = function(method, async, callback, wsdl, req) \n{\n\tvar o = null;\n\tvar nd = SOAPClient._getElementsByTagName(req.responseXML, method + \"Result\");\n\tif(nd.length == 0)\n\t\tnd = SOAPClient._getElementsByTagName(req.responseXML, \"return\");\t// PHP web Service?\n\tif(nd.length == 0)\n\t{\n\t\tif(req.responseXML.getElementsByTagName(\"faultcode\").length > 0)\n\t\t{\n\t\t if(async || callback)\n\t\t o = new Error(500, req.responseXML.getElementsByTagName(\"faultstring\")[0].childNodes[0].nodeValue);\n\t\t\telse\n\t\t\t throw new Error(500, req.responseXML.getElementsByTagName(\"faultstring\")[0].childNodes[0].nodeValue);\t\t\t\n\t\t}\n\t}\n\telse\n\t\to = SOAPClient._soapresult2object(nd[0], wsdl);\n\tif(callback)\n\t\tcallback(o, req.responseXML);\n\tif(!async)\n\t\treturn o;\n}\nSOAPClient._soapresult2object = function(node, wsdl)\n{\n var wsdlTypes = SOAPClient._getTypesFromWsdl(wsdl);\n return SOAPClient._node2object(node, wsdlTypes);\n}\nSOAPClient._node2object = function(node, wsdlTypes)\n{\n\t// null node\n\tif(node == null)\n\t\treturn null;\n\t// text node\n\tif(node.nodeType == 3 || node.nodeType == 4)\n\t\treturn SOAPClient._extractValue(node, wsdlTypes);\n\t// leaf node\n\tif (node.childNodes.length == 1 && (node.childNodes[0].nodeType == 3 || node.childNodes[0].nodeType == 4))\n\t\treturn SOAPClient._node2object(node.childNodes[0], wsdlTypes);\n\tvar isarray = SOAPClient._getTypeFromWsdl(node.nodeName, wsdlTypes).toLowerCase().indexOf(\"arrayof\") != -1;\n\t// object node\n\tif(!isarray)\n\t{\n\t\tvar obj = null;\n\t\tif(node.hasChildNodes())\n\t\t\tobj = new Object();\n\t\tfor(var i = 0; i < node.childNodes.length; i++)\n\t\t{\n\t\t\tvar p = SOAPClient._node2object(node.childNodes[i], wsdlTypes);\n\t\t\tobj[node.childNodes[i].nodeName] = p;\n\t\t}\n\t\treturn obj;\n\t}\n\t// list node\n\telse\n\t{\n\t\t// create node ref\n\t\tvar l = new Array();\n\t\tfor(var i = 0; i < node.childNodes.length; i++)\n\t\t\tl[l.length] = SOAPClient._node2object(node.childNodes[i], wsdlTypes);\n\t\treturn l;\n\t}\n\treturn null;\n}\nSOAPClient._extractValue = function(node, wsdlTypes)\n{\n\tvar value = node.nodeValue;\n\tswitch(SOAPClient._getTypeFromWsdl(node.parentNode.nodeName, wsdlTypes).toLowerCase())\n\t{\n\t\tdefault:\n\t\tcase \"s:string\":\t\t\t\n\t\t\treturn (value != null) ? value + \"\" : \"\";\n\t\tcase \"s:boolean\":\n\t\t\treturn value + \"\" == \"true\";\n\t\tcase \"s:int\":\n\t\tcase \"s:long\":\n\t\t\treturn (value != null) ? parseInt(value + \"\", 10) : 0;\n\t\tcase \"s:double\":\n\t\t\treturn (value != null) ? parseFloat(value + \"\") : 0;\n\t\tcase \"s:datetime\":\n\t\t\tif(value == null)\n\t\t\t\treturn null;\n\t\t\telse\n\t\t\t{\n\t\t\t\tvalue = value + \"\";\n\t\t\t\tvalue = value.substring(0, (value.lastIndexOf(\".\") == -1 ? value.length : value.lastIndexOf(\".\")));\n\t\t\t\tvalue = value.replace(/T/gi,\" \");\n\t\t\t\tvalue = value.replace(/-/gi,\"/\");\n\t\t\t\tvar d = new Date();\n\t\t\t\td.setTime(Date.parse(value));\t\t\t\t\t\t\t\t\t\t\n\t\t\t\treturn d;\t\t\t\t\n\t\t\t}\n\t}\n}\nSOAPClient._getTypesFromWsdl = function(wsdl)\n{\n\tvar wsdlTypes = new Array();\n\t// IE\n\tvar ell = wsdl.getElementsByTagName(\"s:element\");\t\n\tvar useNamedItem = true;\n\t// MOZ\n\tif(ell.length == 0)\n\t{\n\t\tell = wsdl.getElementsByTagName(\"element\");\t \n\t\tuseNamedItem = false;\n\t}\n\tfor(var i = 0; i < ell.length; i++)\n\t{\n\t\tif(useNamedItem)\n\t\t{\n\t\t\tif(ell[i].attributes.getNamedItem(\"name\") != null && ell[i].attributes.getNamedItem(\"type\") != null) \n\t\t\t\twsdlTypes[ell[i].attributes.getNamedItem(\"name\").nodeValue] = ell[i].attributes.getNamedItem(\"type\").nodeValue;\n\t\t}\t\n\t\telse\n\t\t{\n\t\t\tif(ell[i].attributes[\"name\"] != null && ell[i].attributes[\"type\"] != null)\n\t\t\t\twsdlTypes[ell[i].attributes[\"name\"].value] = ell[i].attributes[\"type\"].value;\n\t\t}\n\t}\n\treturn wsdlTypes;\n}\nSOAPClient._getTypeFromWsdl = function(elementname, wsdlTypes)\n{\n var type = wsdlTypes[elementname] + \"\";\n return (type == \"undefined\") ? \"\" : type;\n}\n// private: utils\nSOAPClient._getElementsByTagName = function(document, tagName)\n{\n\ttry\n\t{\n\t\t// trying to get node omitting any namespaces (latest versions of MSXML.XMLDocument)\n\t\treturn document.selectNodes(\".//*[local-name()=\\\"\"+ tagName +\"\\\"]\");\n\t}\n\tcatch (ex) {}\n\t// old XML parser support\n\treturn document.getElementsByTagName(tagName);\n}\n// private: xmlhttp factory\nSOAPClient._getXmlHttp = function() \n{\n\ttry\n\t{\n\t\tif(window.XMLHttpRequest) \n\t\t{\n\t\t\tvar req = new XMLHttpRequest();\n\t\t\t// some versions of Moz do not support the readyState property and the onreadystate event so we patch it!\n\t\t\tif(req.readyState == null) \n\t\t\t{\n\t\t\t\treq.readyState = 1;\n\t\t\t\treq.addEventListener(\"load\", \n\t\t\t\t\t\t\t\t\tfunction() \n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\treq.readyState = 4;\n\t\t\t\t\t\t\t\t\t\tif(typeof req.onreadystatechange == \"function\")\n\t\t\t\t\t\t\t\t\t\t\treq.onreadystatechange();\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tfalse);\n\t\t\t}\n\t\t\treturn req;\n\t\t}\n\t\tif(window.ActiveXObject) \n\t\t\treturn new ActiveXObject(SOAPClient._getXmlHttpProgID());\n\t}\n\tcatch (ex) {}\n\tthrow new Error(\"Your browser does not support XmlHttp objects\");\n}\nSOAPClient._getXmlHttpProgID = function()\n{\n\tif(SOAPClient._getXmlHttpProgID.progid)\n\t\treturn SOAPClient._getXmlHttpProgID.progid;\n\tvar progids = [\"Msxml2.XMLHTTP.5.0\", \"Msxml2.XMLHTTP.4.0\", \"MSXML2.XMLHTTP.3.0\", \"MSXML2.XMLHTTP\", \"Microsoft.XMLHTTP\"];\n\tvar o;\n\tfor(var i = 0; i < progids.length; i++)\n\t{\n\t\ttry\n\t\t{\n\t\t\to = new ActiveXObject(progids[i]);\n\t\t\treturn SOAPClient._getXmlHttpProgID.progid = progids[i];\n\t\t}\n\t\tcatch (ex) {};\n\t}\n\tthrow new Error(\"Could not find an installed XML parser\");\n}\n\nSOAPClient._toBase64 = function(input)\n{\n\tvar keyStr = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\tvar output = \"\";\n\tvar chr1, chr2, chr3;\n\tvar enc1, enc2, enc3, enc4;\n\tvar i = 0;\n\n\tdo {\n\t\tchr1 = input.charCodeAt(i++);\n\t\tchr2 = input.charCodeAt(i++);\n\t\tchr3 = input.charCodeAt(i++);\n\n\t\tenc1 = chr1 >> 2;\n\t\tenc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n\t\tenc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n\t\tenc4 = chr3 & 63;\n\n\t\tif (isNaN(chr2)) {\n\t\t\tenc3 = enc4 = 64;\n\t\t} else if (isNaN(chr3)) {\n\t\t\tenc4 = 64;\n\t\t}\n\n\t\toutput = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) +\n\t\tkeyStr.charAt(enc3) + keyStr.charAt(enc4);\n\t} while (i < input.length);\n\n\treturn output;\n}\n\nangular.module('angularSoap', [])\n\n.factory(\"$soap\",['$q',function($q){\n\treturn {\n\t\tpost: function(url, action, params){\n\t\t\tvar deferred = $q.defer();\n\t\t\t\n\t\t\t//Create SOAPClientParameters\n\t\t\tvar soapParams = new SOAPClientParameters();\n\t\t\tfor(var param in params){\n\t\t\t\tsoapParams.add(param, params[param]);\n\t\t\t}\n\t\t\t\n\t\t\t//Create Callback\n\t\t\tvar soapCallback = function(e){\n\t\t\t\tif(e.constructor.toString().indexOf(\"function Error()\") != -1){\n\t\t\t\t\tdeferred.reject(\"An error has occurred.\");\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.resolve(e);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tSOAPClient.invoke(url, action, soapParams, true, soapCallback);\n\n\t\t\treturn deferred.promise;\n\t\t},\n\t\tsetCredentials: function(username, password){\n\t\t\tSOAPClient.username = username;\n\t\t\tSOAPClient.password = password;\n\t\t}\n\t}\n}]);\n\n/*!\n angular-block-ui v0.2.1\n (c) 2015 (null) McNull https://github.com/McNull/angular-block-ui\n License: MIT\n*/\n(function(angular) {\n\nvar blkUI = angular.module('blockUI', []);\n\nblkUI.config([\"$provide\", \"$httpProvider\", function ($provide, $httpProvider) {\n\n $provide.decorator('$exceptionHandler', ['$delegate', '$injector',\n function ($delegate, $injector) {\n var blockUI, blockUIConfig;\n\n return function (exception, cause) {\n\n blockUIConfig = blockUIConfig || $injector.get('blockUIConfig');\n\n if (blockUIConfig.resetOnException) {\n try {\n blockUI = blockUI || $injector.get('blockUI');\n blockUI.instances.reset();\n } catch (ex) {\n console.log('$exceptionHandler', exception);\n }\n }\n\n $delegate(exception, cause);\n };\n }\n ]);\n\n $httpProvider.interceptors.push('blockUIHttpInterceptor');\n}]);\n\nblkUI.run([\"$document\", \"blockUIConfig\", \"$templateCache\", function ($document, blockUIConfig, $templateCache) {\n if (blockUIConfig.autoInjectBodyBlock) {\n $document.find('body').attr('block-ui', 'main');\n }\n\n if (blockUIConfig.template) {\n\n // Swap the builtin template with the custom template.\n // Create a magic cache key and place the template in the cache.\n\n blockUIConfig.templateUrl = '$$block-ui-template$$';\n $templateCache.put(blockUIConfig.templateUrl, blockUIConfig.template);\n }\n}]);\n\nfunction moduleLoaded(name) {\n try {\n angular.module(name);\n } catch(ex) {\n return false;\n }\n return true;\n}\nblkUI.config([\"$provide\", function ($provide) {\n $provide.decorator('$location', decorateLocation);\n}]);\n\nvar decorateLocation = [\n '$delegate', 'blockUI', 'blockUIConfig',\n function ($delegate, blockUI, blockUIConfig) {\n\n if (blockUIConfig.blockBrowserNavigation) {\n\n blockUI.$_blockLocationChange = true;\n\n var overrides = ['url', 'path', 'search', 'hash', 'state'];\n\n function hook(f) {\n var s = $delegate[f];\n $delegate[f] = function () {\n\n // console.log(f, Date.now(), arguments);\n\n var result = s.apply($delegate, arguments);\n\n // The call was a setter if the $location service is returned.\n\n if (result === $delegate) {\n\n // Mark the mainblock ui to allow the location change.\n\n blockUI.$_blockLocationChange = false;\n }\n\n return result;\n };\n }\n\n angular.forEach(overrides, hook);\n\n }\n\n return $delegate;\n}];\n\n// Called from block-ui-directive for the 'main' instance.\n\nfunction blockNavigation($scope, mainBlockUI, blockUIConfig) {\n\n if (blockUIConfig.blockBrowserNavigation) {\n\n function registerLocationChange() {\n\n $scope.$on('$locationChangeStart', function (event) {\n\n // console.log('$locationChangeStart', mainBlockUI.$_blockLocationChange + ' ' + mainBlockUI.state().blockCount);\n\n if (mainBlockUI.$_blockLocationChange && mainBlockUI.state().blockCount > 0) {\n event.preventDefault();\n }\n });\n\n $scope.$on('$locationChangeSuccess', function () {\n mainBlockUI.$_blockLocationChange = blockUIConfig.blockBrowserNavigation;\n\n // console.log('$locationChangeSuccess', mainBlockUI.$_blockLocationChange + ' ' + mainBlockUI.state().blockCount);\n });\n }\n\n if (moduleLoaded('ngRoute')) {\n\n // After the initial content has been loaded we'll spy on any location\n // changes and discard them when needed.\n\n var fn = $scope.$on('$viewContentLoaded', function () {\n\n // Unhook the view loaded and hook a function that will prevent\n // location changes while the block is active.\n\n fn();\n registerLocationChange();\n\n });\n\n } else {\n registerLocationChange();\n }\n\n }\n}\nblkUI.directive('blockUiContainer', [\"blockUIConfig\", \"blockUiContainerLinkFn\", function (blockUIConfig, blockUiContainerLinkFn) {\n return {\n scope: true,\n restrict: 'A',\n templateUrl: blockUIConfig.templateUrl,\n compile: function($element) {\n return blockUiContainerLinkFn;\n }\n };\n}]).factory('blockUiContainerLinkFn', [\"blockUI\", \"blockUIUtils\", function (blockUI, blockUIUtils) {\n\n return function ($scope, $element, $attrs) {\n\n var srvInstance = $element.inheritedData('block-ui');\n\n if (!srvInstance) {\n throw new Error('No parent block-ui service instance located.');\n }\n\n // Expose the state on the scope\n\n $scope.state = srvInstance.state();\n\n// $scope.$watch('state.blocking', function(value) {\n// $element.toggleClass('block-ui-visible', !!value);\n// });\n//\n// $scope.$watch('state.blockCount > 0', function(value) {\n// $element.toggleClass('block-ui-active', !!value);\n// });\n };\n}]);\nblkUI.directive('blockUi', [\"blockUiCompileFn\", function (blockUiCompileFn) {\n\n return {\n scope: true,\n restrict: 'A',\n compile: blockUiCompileFn\n };\n\n}]).factory('blockUiCompileFn', [\"blockUiPreLinkFn\", function (blockUiPreLinkFn) {\n\n return function ($element, $attrs) {\n\n // Class should be added here to prevent an animation delay error.\n\n $element.append('
');\n\n return {\n pre: blockUiPreLinkFn\n };\n\n };\n\n}]).factory('blockUiPreLinkFn', [\"blockUI\", \"blockUIUtils\", \"blockUIConfig\", function (blockUI, blockUIUtils, blockUIConfig) {\n\n return function ($scope, $element, $attrs) {\n\n // If the element does not have the class \"block-ui\" set, we set the\n // default css classes from the config.\n\n if (!$element.hasClass('block-ui')) {\n $element.addClass(blockUIConfig.cssClass);\n }\n\n // Expose the blockUiMessageClass attribute value on the scope\n\n $attrs.$observe('blockUiMessageClass', function (value) {\n $scope.$_blockUiMessageClass = value;\n });\n\n // Create the blockUI instance\n // Prefix underscore to prevent integers:\n // https://github.com/McNull/angular-block-ui/pull/8\n\n var instanceId = $attrs.blockUi || '_' + $scope.$id;\n var srvInstance = blockUI.instances.get(instanceId);\n\n // If this is the main (topmost) block element we'll also need to block any\n // location changes while the block is active.\n\n if (instanceId === 'main') {\n blockNavigation($scope, srvInstance, blockUIConfig);\n } else {\n // Locate the parent blockUI instance\n var parentInstance = $element.inheritedData('block-ui');\n\n if (parentInstance) {\n // TODO: assert if parent is already set to something else\n srvInstance._parent = parentInstance;\n }\n }\n\n // Ensure the instance is released when the scope is destroyed\n\n $scope.$on('$destroy', function () {\n srvInstance.release();\n });\n\n // Increase the reference count\n\n srvInstance.addRef();\n\n // Expose the state on the scope\n\n $scope.$_blockUiState = srvInstance.state();\n\n $scope.$watch('$_blockUiState.blocking', function (value) {\n // Set the aria-busy attribute if needed\n $element.attr('aria-busy', !!value);\n $element.toggleClass('block-ui-visible', !!value);\n });\n\n $scope.$watch('$_blockUiState.blockCount > 0', function (value) {\n $element.toggleClass('block-ui-active', !!value);\n });\n\n // If a pattern is provided assign it to the state\n\n var pattern = $attrs.blockUiPattern;\n\n if (pattern) {\n var regExp = blockUIUtils.buildRegExp(pattern);\n srvInstance.pattern(regExp);\n }\n\n // Store a reference to the service instance on the element\n\n $element.data('block-ui', srvInstance);\n\n };\n\n}]);\n//.factory('blockUiPostLinkFn', function(blockUIUtils) {\n//\n// return function($scope, $element, $attrs) {\n//\n// var $message;\n//\n// $attrs.$observe('blockUiMessageClass', function(value) {\n//\n// $message = $message || blockUIUtils.findElement($element, function($e) {\n// return $e.hasClass('block-ui-message');\n// });\n//\n// $message.addClass(value);\n//\n// });\n// };\n//\n//});\nblkUI.constant('blockUIConfig', {\n templateUrl: 'angular-block-ui/angular-block-ui.ng.html',\n delay: 250,\n message: \"Loading ...\",\n autoBlock: true,\n resetOnException: true,\n requestFilter: angular.noop,\n autoInjectBodyBlock: true,\n cssClass: 'block-ui block-ui-anim-fade',\n blockBrowserNavigation: false\n});\n\n\nblkUI.factory('blockUIHttpInterceptor', [\"$q\", \"$injector\", \"blockUIConfig\", \"$templateCache\", function($q, $injector, blockUIConfig, $templateCache) {\n\n var blockUI;\n\n function injectBlockUI() {\n blockUI = blockUI || $injector.get('blockUI');\n }\n\n function stopBlockUI(config) {\n if (blockUIConfig.autoBlock && (config && !config.$_noBlock && config.$_blocks)) {\n injectBlockUI();\n config.$_blocks.stop();\n }\n }\n\n function error(rejection) {\n\n try {\n stopBlockUI(rejection.config);\n } catch(ex) {\n console.log('httpRequestError', ex);\n }\n\n return $q.reject(rejection);\n }\n\n return {\n request: function(config) {\n\n // Only block when autoBlock is enabled ...\n // ... and the request doesn't match a cached template.\n\n if (blockUIConfig.autoBlock &&\n !(config.method == 'GET' && $templateCache.get(config.url))) {\n\n // Don't block excluded requests\n\n var result = blockUIConfig.requestFilter(config);\n\n if (result === false) {\n // Tag the config so we don't unblock this request\n config.$_noBlock = true;\n } else {\n\n injectBlockUI();\n\n config.$_blocks = blockUI.instances.locate(config);\n config.$_blocks.start(result);\n }\n }\n\n return config;\n },\n\n requestError: error,\n\n response: function(response) {\n\n // If the connection to the website goes down the response interceptor gets and error with \"cannot read property config of null\".\n // https://github.com/McNull/angular-block-ui/issues/53\n\n if(response) {\n stopBlockUI(response.config);\n }\n\n return response;\n },\n\n responseError: error\n };\n\n}]);\n\nblkUI.factory('blockUI', [\"blockUIConfig\", \"$timeout\", \"blockUIUtils\", \"$document\", function(blockUIConfig, $timeout, blockUIUtils, $document) {\n\n var $body = $document.find('body');\n \n // These properties are not allowed to be specified in the start method.\n var reservedStateProperties = ['id', 'blockCount', 'blocking'];\n \n function BlockUI(id) {\n\n var self = this;\n\n var state = {\n id: id,\n blockCount: 0,\n message: blockUIConfig.message,\n blocking: false\n }, startPromise, doneCallbacks = [];\n\n this._id = id;\n\n this._refs = 0;\n\n this.start = function(messageOrOptions) {\n \n messageOrOptions = messageOrOptions || {};\n \n if(angular.isString(messageOrOptions)) {\n messageOrOptions = {\n message: messageOrOptions\n };\n } else {\n angular.forEach(reservedStateProperties, function(x) {\n if(messageOrOptions[x]) {\n throw new Error('The property ' + x + ' is reserved for the block state.');\n }\n });\n } \n \n angular.extend(state, messageOrOptions);\n \n if(state.blockCount > 0) {\n state.message = messageOrOptions.message || state.message || blockUIConfig.message;\n } else {\n state.message = messageOrOptions.message || blockUIConfig.message;\n }\n \n // if(state.blockCount > 0) {\n // messageOrOptions = messageOrOptions || state.message || blockUIConfig.message;\n // } else {\n // messageOrOptions = messageOrOptions || blockUIConfig.message;\n // }\n\n // state.message = messageOrOptions;\n\n state.blockCount++;\n\n // Check if the focused element is part of the block scope\n\n var $ae = angular.element($document[0].activeElement);\n\n if($ae.length && blockUIUtils.isElementInBlockScope($ae, self)) {\n\n // Let the active element lose focus and store a reference \n // to restore focus when we're done (reset)\n\n self._restoreFocus = $ae[0];\n\n // https://github.com/McNull/angular-block-ui/issues/13\n // http://stackoverflow.com/questions/22698058/apply-already-in-progress-error-when-using-typeahead-plugin-found-to-be-relate\n // Queue the blur after any ng-blur expression.\n\n $timeout(function() {\n // Ensure we still need to blur\n // Don't restore if active element is body, since this causes IE to switch windows (see http://tjvantoll.com/2013/08/30/bugs-with-document-activeelement-in-internet-explorer/)\n if (self._restoreFocus && self._restoreFocus !== $body[0]) {\n self._restoreFocus.blur();\n }\n });\n }\n\n if (!startPromise && blockUIConfig.delay !== 0) {\n startPromise = $timeout(block, blockUIConfig.delay);\n } else if (blockUIConfig.delay === 0) {\n block();\n }\n\n function block () {\n startPromise = null;\n state.blocking = true;\n }\n };\n\n this._cancelStartTimeout = function() {\n if (startPromise) {\n $timeout.cancel(startPromise);\n startPromise = null;\n }\n };\n\n this.stop = function() {\n state.blockCount = Math.max(0, --state.blockCount);\n\n if (state.blockCount === 0) {\n self.reset(true);\n }\n };\n\n this.isBlocking = function () {\n return state.blocking;\n };\n\n this.message = function(value) {\n state.message = value;\n };\n\n this.pattern = function(regexp) {\n if (regexp !== undefined) {\n self._pattern = regexp;\n }\n\n return self._pattern;\n };\n\n this.reset = function(executeCallbacks) {\n \n self._cancelStartTimeout();\n state.blockCount = 0;\n state.blocking = false;\n\n // Restore the focus to the element that was active\n // before the block start, but not if the user has \n // focused something else while the block was active.\n\n if(self._restoreFocus && \n (!$document[0].activeElement || $document[0].activeElement === $body[0])) {\n \n //IE8 will throw if element for setting focus is invisible\n try {\n self._restoreFocus.focus();\n } catch(e1) {\n (function () {\n var elementToFocus = self._restoreFocus;\n $timeout(function() { \n if(elementToFocus) { \n try { \n elementToFocus.focus(); \n } catch(e2) { }\n } \n },100);\n })();\n }\n \n self._restoreFocus = null;\n }\n \n try {\n if (executeCallbacks) {\n angular.forEach(doneCallbacks, function(cb) {\n cb();\n });\n }\n } finally {\n doneCallbacks.length = 0;\n }\n };\n\n this.done = function(fn) {\n doneCallbacks.push(fn);\n };\n\n this.state = function() {\n return state;\n };\n\n this.addRef = function() {\n self._refs += 1;\n };\n\n this.release = function() {\n if(--self._refs <= 0) {\n mainBlock.instances._destroy(self);\n }\n };\n }\n\n var instances = [];\n\n instances.get = function(id) {\n\n if(!isNaN(id)) {\n throw new Error('BlockUI id cannot be a number');\n }\n\n var instance = instances[id];\n\n if(!instance) {\n // TODO: ensure no array instance trashing [xxx] -- current workaround: '_' + $scope.$id\n instance = instances[id] = new BlockUI(id);\n instances.push(instance);\n }\n\n return instance;\n };\n\n instances._destroy = function(idOrInstance) {\n if (angular.isString(idOrInstance)) {\n idOrInstance = instances[idOrInstance];\n }\n\n if (idOrInstance) {\n idOrInstance.reset();\n\n var i = blockUIUtils.indexOf(instances, idOrInstance);\n instances.splice(i, 1);\n\n delete instances[idOrInstance.state().id];\n }\n };\n \n instances.locate = function(request) {\n\n var result = [];\n\n // Add function wrappers that will be executed on every item\n // in the array.\n \n blockUIUtils.forEachFnHook(result, 'start');\n blockUIUtils.forEachFnHook(result, 'stop');\n\n var i = instances.length;\n\n while(i--) {\n var instance = instances[i];\n var pattern = instance._pattern;\n\n if(pattern && pattern.test(request.url)) {\n result.push(instance);\n }\n }\n\n if(result.length === 0) {\n result.push(mainBlock);\n }\n\n return result;\n };\n\n // Propagate the reset to all instances\n\n blockUIUtils.forEachFnHook(instances, 'reset');\n\n var mainBlock = instances.get('main');\n\n mainBlock.addRef();\n mainBlock.instances = instances;\n\n return mainBlock;\n}]);\n\n\nblkUI.factory('blockUIUtils', function() {\n\n var $ = angular.element;\n\n var utils = {\n buildRegExp: function(pattern) {\n var match = pattern.match(/^\\/(.*)\\/([gim]*)$/), regExp;\n\n if(match) {\n regExp = new RegExp(match[1], match[2]);\n } else {\n throw Error('Incorrect regular expression format: ' + pattern);\n }\n\n return regExp;\n },\n forEachFn: function(arr, fnName, args) {\n var i = arr.length;\n while(i--) {\n var t = arr[i];\n t[fnName].apply(t, args);\n }\n },\n forEachFnHook: function(arr, fnName) {\n arr[fnName] = function() {\n utils.forEachFn(this, fnName, arguments);\n }\n },\n isElementInBlockScope: function($element, blockScope) {\n var c = $element.inheritedData('block-ui');\n\n while(c) {\n if(c === blockScope) {\n return true;\n }\n\n c = c._parent;\n }\n\n return false;\n },\n findElement: function ($element, predicateFn, traverse) {\n var ret = null;\n\n if (predicateFn($element)) {\n ret = $element;\n } else {\n\n var $elements;\n\n if (traverse) {\n $elements = $element.parent();\n } else {\n $elements = $element.children();\n }\n\n var i = $elements.length;\n while (!ret && i--) {\n ret = utils.findElement($($elements[i]), predicateFn, traverse);\n }\n }\n\n return ret;\n },\n indexOf: function(arr, obj, start) {\n// if(Array.prototype.indexOf) {\n// return arr.indexOf(obj, start);\n// }\n\n for (var i = (start || 0), j = arr.length; i < j; i++) {\n if (arr[i] === obj) {\n return i;\n }\n }\n\n return -1;\n }\n };\n\n return utils;\n\n});\n// Automatically generated.\n// This file is already embedded in your main javascript output, there's no need to include this file\n// manually in the index.html. This file is only here for your debugging pleasures.\nangular.module('blockUI').run(['$templateCache', function($templateCache){\n $templateCache.put('angular-block-ui/angular-block-ui.ng.html', '
');\n}]);\n})(angular);\n//# sourceMappingURL=angular-block-ui.js.map\n/* angular-moment.js / v0.10.3 / (c) 2013, 2014, 2015 Uri Shaked / MIT Licence */\n\n'format amd';\n/* global define */\n\n(function () {\n\t'use strict';\n\n\tfunction angularMoment(angular, moment) {\n\n\t\t/**\n\t\t * @ngdoc overview\n\t\t * @name angularMoment\n\t\t *\n\t\t * @description\n\t\t * angularMoment module provides moment.js functionality for angular.js apps.\n\t\t */\n\t\treturn angular.module('angularMoment', [])\n\n\t\t/**\n\t\t * @ngdoc object\n\t\t * @name angularMoment.config:angularMomentConfig\n\t\t *\n\t\t * @description\n\t\t * Common configuration of the angularMoment module\n\t\t */\n\t\t\t.constant('angularMomentConfig', {\n\t\t\t\t/**\n\t\t\t\t * @ngdoc property\n\t\t\t\t * @name angularMoment.config.angularMomentConfig#preprocess\n\t\t\t\t * @propertyOf angularMoment.config:angularMomentConfig\n\t\t\t\t * @returns {string} The default preprocessor to apply\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * Defines a default preprocessor to apply (e.g. 'unix', 'etc', ...). The default value is null,\n\t\t\t\t * i.e. no preprocessor will be applied.\n\t\t\t\t */\n\t\t\t\tpreprocess: null, // e.g. 'unix', 'utc', ...\n\n\t\t\t\t/**\n\t\t\t\t * @ngdoc property\n\t\t\t\t * @name angularMoment.config.angularMomentConfig#timezone\n\t\t\t\t * @propertyOf angularMoment.config:angularMomentConfig\n\t\t\t\t * @returns {string} The default timezone\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * The default timezone (e.g. 'Europe/London'). Empty string by default (does not apply\n\t\t\t\t * any timezone shift).\n\t\t\t\t */\n\t\t\t\ttimezone: '',\n\n\t\t\t\t/**\n\t\t\t\t * @ngdoc property\n\t\t\t\t * @name angularMoment.config.angularMomentConfig#format\n\t\t\t\t * @propertyOf angularMoment.config:angularMomentConfig\n\t\t\t\t * @returns {string} The pre-conversion format of the date\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * Specify the format of the input date. Essentially it's a\n\t\t\t\t * default and saves you from specifying a format in every\n\t\t\t\t * element. Overridden by element attr. Null by default.\n\t\t\t\t */\n\t\t\t\tformat: null,\n\n\t\t\t\t/**\n\t\t\t\t * @ngdoc property\n\t\t\t\t * @name angularMoment.config.angularMomentConfig#statefulFilters\n\t\t\t\t * @propertyOf angularMoment.config:angularMomentConfig\n\t\t\t\t * @returns {boolean} Whether angular-moment filters should be stateless (or not)\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * Specifies whether the filters included with angular-moment are stateful.\n\t\t\t\t * Stateful filters will automatically re-evaluate whenever you change the timezone\n\t\t\t\t * or language settings, but may negatively impact performance. true by default.\n\t\t\t\t */\n\t\t\t\tstatefulFilters: true\n\t\t\t})\n\n\t\t/**\n\t\t * @ngdoc object\n\t\t * @name angularMoment.object:moment\n\t\t *\n\t\t * @description\n\t\t * moment global (as provided by the moment.js library)\n\t\t */\n\t\t\t.constant('moment', moment)\n\n\t\t/**\n\t\t * @ngdoc object\n\t\t * @name angularMoment.config:amTimeAgoConfig\n\t\t * @module angularMoment\n\t\t *\n\t\t * @description\n\t\t * configuration specific to the amTimeAgo directive\n\t\t */\n\t\t\t.constant('amTimeAgoConfig', {\n\t\t\t\t/**\n\t\t\t\t * @ngdoc property\n\t\t\t\t * @name angularMoment.config.amTimeAgoConfig#withoutSuffix\n\t\t\t\t * @propertyOf angularMoment.config:amTimeAgoConfig\n\t\t\t\t * @returns {boolean} Whether to include a suffix in am-time-ago directive\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * Defaults to false.\n\t\t\t\t */\n\t\t\t\twithoutSuffix: false,\n\n\t\t\t\t/**\n\t\t\t\t * @ngdoc property\n\t\t\t\t * @name angularMoment.config.amTimeAgoConfig#serverTime\n\t\t\t\t * @propertyOf angularMoment.config:amTimeAgoConfig\n\t\t\t\t * @returns {number} Server time in milliseconds since the epoch\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * If set, time ago will be calculated relative to the given value.\n\t\t\t\t * If null, local time will be used. Defaults to null.\n\t\t\t\t */\n\t\t\t\tserverTime: null,\n\n\t\t\t\t/**\n\t\t\t\t * @ngdoc property\n\t\t\t\t * @name angularMoment.config.amTimeAgoConfig#titleFormat\n\t\t\t\t * @propertyOf angularMoment.config:amTimeAgoConfig\n\t\t\t\t * @returns {string} The format of the date to be displayed in the title of the element. If null,\n\t\t\t\t * the directive set the title of the element.\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * The format of the date used for the title of the element. null by default.\n\t\t\t\t */\n\t\t\t\ttitleFormat: null,\n\n\t\t\t\t/**\n\t\t\t\t * @ngdoc property\n\t\t\t\t * @name angularMoment.config.amTimeAgoConfig#fullDateThreshold\n\t\t\t\t * @propertyOf angularMoment.config:amTimeAgoConfig\n\t\t\t\t * @returns {number} The minimum number of days for showing a full date instead of relative time\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * The threshold for displaying a full date. The default is null, which means the date will always\n\t\t\t\t * be relative, and full date will never be displayed.\n\t\t\t\t */\n\t\t\t\tfullDateThreshold: null,\n\n\t\t\t\t/**\n\t\t\t\t * @ngdoc property\n\t\t\t\t * @name angularMoment.config.amTimeAgoConfig#fullDateFormat\n\t\t\t\t * @propertyOf angularMoment.config:amTimeAgoConfig\n\t\t\t\t * @returns {string} The format to use when displaying a full date.\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * Specify the format of the date when displayed as full date. null by default.\n\t\t\t\t */\n\t\t\t\tfullDateFormat: null\n\t\t\t})\n\n\t\t/**\n\t\t * @ngdoc directive\n\t\t * @name angularMoment.directive:amTimeAgo\n\t\t * @module angularMoment\n\t\t *\n\t\t * @restrict A\n\t\t */\n\t\t\t.directive('amTimeAgo', ['$window', 'moment', 'amMoment', 'amTimeAgoConfig', 'angularMomentConfig', function ($window, moment, amMoment, amTimeAgoConfig, angularMomentConfig) {\n\n\t\t\t\treturn function (scope, element, attr) {\n\t\t\t\t\tvar activeTimeout = null;\n\t\t\t\t\tvar currentValue;\n\t\t\t\t\tvar currentFormat = angularMomentConfig.format;\n\t\t\t\t\tvar withoutSuffix = amTimeAgoConfig.withoutSuffix;\n\t\t\t\t\tvar titleFormat = amTimeAgoConfig.titleFormat;\n\t\t\t\t\tvar fullDateThreshold = amTimeAgoConfig.fullDateThreshold;\n\t\t\t\t\tvar fullDateFormat = amTimeAgoConfig.fullDateFormat;\n\t\t\t\t\tvar localDate = new Date().getTime();\n\t\t\t\t\tvar preprocess = angularMomentConfig.preprocess;\n\t\t\t\t\tvar modelName = attr.amTimeAgo;\n\t\t\t\t\tvar currentFrom;\n\t\t\t\t\tvar isTimeElement = ('TIME' === element[0].nodeName.toUpperCase());\n\n\t\t\t\t\tfunction getNow() {\n\t\t\t\t\t\tvar now;\n\t\t\t\t\t\tif (currentFrom) {\n\t\t\t\t\t\t\tnow = currentFrom;\n\t\t\t\t\t\t} else if (amTimeAgoConfig.serverTime) {\n\t\t\t\t\t\t\tvar localNow = new Date().getTime();\n\t\t\t\t\t\t\tvar nowMillis = localNow - localDate + amTimeAgoConfig.serverTime;\n\t\t\t\t\t\t\tnow = moment(nowMillis);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tnow = moment();\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn now;\n\t\t\t\t\t}\n\n\t\t\t\t\tfunction cancelTimer() {\n\t\t\t\t\t\tif (activeTimeout) {\n\t\t\t\t\t\t\t$window.clearTimeout(activeTimeout);\n\t\t\t\t\t\t\tactiveTimeout = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfunction updateTime(momentInstance) {\n\t\t\t\t\t\tvar daysAgo = getNow().diff(momentInstance, 'day');\n\t\t\t\t\t\tvar showFullDate = fullDateThreshold && daysAgo >= fullDateThreshold;\n\n\t\t\t\t\t\tif (showFullDate) {\n\t\t\t\t\t\t\telement.text(momentInstance.format(fullDateFormat));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\telement.text(momentInstance.from(getNow(), withoutSuffix));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (titleFormat && !element.attr('title')) {\n\t\t\t\t\t\t\telement.attr('title', momentInstance.local().format(titleFormat));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!showFullDate) {\n\t\t\t\t\t\t\tvar howOld = Math.abs(getNow().diff(momentInstance, 'minute'));\n\t\t\t\t\t\t\tvar secondsUntilUpdate = 3600;\n\t\t\t\t\t\t\tif (howOld < 1) {\n\t\t\t\t\t\t\t\tsecondsUntilUpdate = 1;\n\t\t\t\t\t\t\t} else if (howOld < 60) {\n\t\t\t\t\t\t\t\tsecondsUntilUpdate = 30;\n\t\t\t\t\t\t\t} else if (howOld < 180) {\n\t\t\t\t\t\t\t\tsecondsUntilUpdate = 300;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tactiveTimeout = $window.setTimeout(function () {\n\t\t\t\t\t\t\t\tupdateTime(momentInstance);\n\t\t\t\t\t\t\t}, secondsUntilUpdate * 1000);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfunction updateDateTimeAttr(value) {\n\t\t\t\t\t\tif (isTimeElement) {\n\t\t\t\t\t\t\telement.attr('datetime', value);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tfunction updateMoment() {\n\t\t\t\t\t\tcancelTimer();\n\t\t\t\t\t\tif (currentValue) {\n\t\t\t\t\t\t\tvar momentValue = amMoment.preprocessDate(currentValue, preprocess, currentFormat);\n\t\t\t\t\t\t\tupdateTime(momentValue);\n\t\t\t\t\t\t\tupdateDateTimeAttr(momentValue.toISOString());\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tscope.$watch(modelName, function (value) {\n\t\t\t\t\t\tif ((typeof value === 'undefined') || (value === null) || (value === '')) {\n\t\t\t\t\t\t\tcancelTimer();\n\t\t\t\t\t\t\tif (currentValue) {\n\t\t\t\t\t\t\t\telement.text('');\n\t\t\t\t\t\t\t\tupdateDateTimeAttr('');\n\t\t\t\t\t\t\t\tcurrentValue = null;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcurrentValue = value;\n\t\t\t\t\t\tupdateMoment();\n\t\t\t\t\t});\n\n\t\t\t\t\tif (angular.isDefined(attr.amFrom)) {\n\t\t\t\t\t\tscope.$watch(attr.amFrom, function (value) {\n\t\t\t\t\t\t\tif ((typeof value === 'undefined') || (value === null) || (value === '')) {\n\t\t\t\t\t\t\t\tcurrentFrom = null;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcurrentFrom = moment(value);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tupdateMoment();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tif (angular.isDefined(attr.amWithoutSuffix)) {\n\t\t\t\t\t\tscope.$watch(attr.amWithoutSuffix, function (value) {\n\t\t\t\t\t\t\tif (typeof value === 'boolean') {\n\t\t\t\t\t\t\t\twithoutSuffix = value;\n\t\t\t\t\t\t\t\tupdateMoment();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twithoutSuffix = amTimeAgoConfig.withoutSuffix;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tattr.$observe('amFormat', function (format) {\n\t\t\t\t\t\tif (typeof format !== 'undefined') {\n\t\t\t\t\t\t\tcurrentFormat = format;\n\t\t\t\t\t\t\tupdateMoment();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tattr.$observe('amPreprocess', function (newValue) {\n\t\t\t\t\t\tpreprocess = newValue;\n\t\t\t\t\t\tupdateMoment();\n\t\t\t\t\t});\n\n\t\t\t\t\tattr.$observe('amFullDateThreshold', function (newValue) {\n\t\t\t\t\t\tfullDateThreshold = newValue;\n\t\t\t\t\t\tupdateMoment();\n\t\t\t\t\t});\n\n\t\t\t\t\tattr.$observe('amFullDateFormat', function (newValue) {\n\t\t\t\t\t\tfullDateFormat = newValue;\n\t\t\t\t\t\tupdateMoment();\n\t\t\t\t\t});\n\n\t\t\t\t\tscope.$on('$destroy', function () {\n\t\t\t\t\t\tcancelTimer();\n\t\t\t\t\t});\n\n\t\t\t\t\tscope.$on('amMoment:localeChanged', function () {\n\t\t\t\t\t\tupdateMoment();\n\t\t\t\t\t});\n\t\t\t\t};\n\t\t\t}])\n\n\t\t/**\n\t\t * @ngdoc service\n\t\t * @name angularMoment.service.amMoment\n\t\t * @module angularMoment\n\t\t */\n\t\t\t.service('amMoment', ['moment', '$rootScope', '$log', 'angularMomentConfig', function (moment, $rootScope, $log, angularMomentConfig) {\n\t\t\t\t/**\n\t\t\t\t * @ngdoc property\n\t\t\t\t * @name angularMoment:amMoment#preprocessors\n\t\t\t\t * @module angularMoment\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * Defines the preprocessors for the preprocessDate method. By default, the following preprocessors\n\t\t\t\t * are defined: utc, unix.\n\t\t\t\t */\n\t\t\t\tthis.preprocessors = {\n\t\t\t\t\tutc: moment.utc,\n\t\t\t\t\tunix: moment.unix\n\t\t\t\t};\n\n\t\t\t\t/**\n\t\t\t\t * @ngdoc function\n\t\t\t\t * @name angularMoment.service.amMoment#changeLocale\n\t\t\t\t * @methodOf angularMoment.service.amMoment\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * Changes the locale for moment.js and updates all the am-time-ago directive instances\n\t\t\t\t * with the new locale. Also broadcasts an `amMoment:localeChanged` event on $rootScope.\n\t\t\t\t *\n\t\t\t\t * @param {string} locale Locale code (e.g. en, es, ru, pt-br, etc.)\n\t\t\t\t * @param {object} customization object of locale strings to override\n\t\t\t\t */\n\t\t\t\tthis.changeLocale = function (locale, customization) {\n\t\t\t\t\tvar result = moment.locale(locale, customization);\n\t\t\t\t\tif (angular.isDefined(locale)) {\n\t\t\t\t\t\t$rootScope.$broadcast('amMoment:localeChanged');\n\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t};\n\n\t\t\t\t/**\n\t\t\t\t * @ngdoc function\n\t\t\t\t * @name angularMoment.service.amMoment#changeTimezone\n\t\t\t\t * @methodOf angularMoment.service.amMoment\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * Changes the default timezone for amCalendar, amDateFormat and amTimeAgo. Also broadcasts an\n\t\t\t\t * `amMoment:timezoneChanged` event on $rootScope.\n\t\t\t\t *\n\t\t\t\t * @param {string} timezone Timezone name (e.g. UTC)\n\t\t\t\t */\n\t\t\t\tthis.changeTimezone = function (timezone) {\n\t\t\t\t\tangularMomentConfig.timezone = timezone;\n\t\t\t\t\t$rootScope.$broadcast('amMoment:timezoneChanged');\n\t\t\t\t};\n\n\t\t\t\t/**\n\t\t\t\t * @ngdoc function\n\t\t\t\t * @name angularMoment.service.amMoment#preprocessDate\n\t\t\t\t * @methodOf angularMoment.service.amMoment\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * Preprocess a given value and convert it into a Moment instance appropriate for use in the\n\t\t\t\t * am-time-ago directive and the filters.\n\t\t\t\t *\n\t\t\t\t * @param {*} value The value to be preprocessed\n\t\t\t\t * @param {string} preprocess The name of the preprocessor the apply (e.g. utc, unix)\n\t\t\t\t * @param {string=} format Specifies how to parse the value (see {@link http://momentjs.com/docs/#/parsing/string-format/})\n\t\t\t\t * @return {Moment} A value that can be parsed by the moment library\n\t\t\t\t */\n\t\t\t\tthis.preprocessDate = function (value, preprocess, format) {\n\t\t\t\t\tif (angular.isUndefined(preprocess)) {\n\t\t\t\t\t\tpreprocess = angularMomentConfig.preprocess;\n\t\t\t\t\t}\n\t\t\t\t\tif (this.preprocessors[preprocess]) {\n\t\t\t\t\t\treturn this.preprocessors[preprocess](value, format);\n\t\t\t\t\t}\n\t\t\t\t\tif (preprocess) {\n\t\t\t\t\t\t$log.warn('angular-moment: Ignoring unsupported value for preprocess: ' + preprocess);\n\t\t\t\t\t}\n\t\t\t\t\tif (!isNaN(parseFloat(value)) && isFinite(value)) {\n\t\t\t\t\t\t// Milliseconds since the epoch\n\t\t\t\t\t\treturn moment(parseInt(value, 10));\n\t\t\t\t\t}\n\t\t\t\t\t// else just returns the value as-is.\n\t\t\t\t\treturn moment(value, format);\n\t\t\t\t};\n\n\t\t\t\t/**\n\t\t\t\t * @ngdoc function\n\t\t\t\t * @name angularMoment.service.amMoment#applyTimezone\n\t\t\t\t * @methodOf angularMoment.service.amMoment\n\t\t\t\t *\n\t\t\t\t * @description\n\t\t\t\t * Apply a timezone onto a given moment object. It can be a named timezone (e.g. 'America/Phoenix') or an offset from UTC (e.g. '+0300')\n\t\t\t\t * moment-timezone.js is needed when a named timezone is used, otherwise, it'll not apply any timezone shift.\n\t\t\t\t *\n\t\t\t\t * @param {Moment} aMoment a moment() instance to apply the timezone shift to\n\t\t\t\t * @param {string=} timezone The timezone to apply. If none given, will apply the timezone\n\t\t\t\t * configured in angularMomentConfig.timezone. It can be a named timezone (e.g. 'America/Phoenix') or an offset from UTC (e.g. '+0300')\n\t\t\t\t *\n\t\t\t\t * @returns {Moment} The given moment with the timezone shift applied\n\t\t\t\t */\n\t\t\t\tthis.applyTimezone = function (aMoment, timezone) {\n\t\t\t\t\ttimezone = timezone || angularMomentConfig.timezone;\n\t\t\t\t\tif (!timezone) {\n\t\t\t\t\t\treturn aMoment;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (timezone.match(/^Z|[+-]\\d\\d:?\\d\\d$/i)) {\n\t\t\t\t\t\taMoment = aMoment.utcOffset(timezone);\n\t\t\t\t\t} else if (aMoment.tz) {\n\t\t\t\t\t\taMoment = aMoment.tz(timezone);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$log.warn('angular-moment: named timezone specified but moment.tz() is undefined. Did you forget to include moment-timezone.js?');\n\t\t\t\t\t}\n\n\t\t\t\t\treturn aMoment;\n\t\t\t\t};\n\t\t\t}])\n\n\t\t/**\n\t\t * @ngdoc filter\n\t\t * @name angularMoment.filter:amCalendar\n\t\t * @module angularMoment\n\t\t */\n\t\t\t.filter('amCalendar', ['moment', 'amMoment', 'angularMomentConfig', function (moment, amMoment, angularMomentConfig) {\n\t\t\t\tfunction amCalendarFilter(value, preprocess, timezone) {\n\t\t\t\t\tif (typeof value === 'undefined' || value === null) {\n\t\t\t\t\t\treturn '';\n\t\t\t\t\t}\n\n\t\t\t\t\tvalue = amMoment.preprocessDate(value, preprocess);\n\t\t\t\t\tvar date = moment(value);\n\t\t\t\t\tif (!date.isValid()) {\n\t\t\t\t\t\treturn '';\n\t\t\t\t\t}\n\n\t\t\t\t\treturn amMoment.applyTimezone(date, timezone).calendar();\n\t\t\t\t}\n\n\t\t\t\t// Since AngularJS 1.3, filters have to explicitly define being stateful\n\t\t\t\t// (this is no longer the default).\n\t\t\t\tamCalendarFilter.$stateful = angularMomentConfig.statefulFilters;\n\n\t\t\t\treturn amCalendarFilter;\n\t\t\t}])\n\n\t\t/**\n\t\t * @ngdoc filter\n\t\t * @name angularMoment.filter:amDifference\n\t\t * @module angularMoment\n\t\t */\n\t\t\t.filter('amDifference', ['moment', 'amMoment', 'angularMomentConfig', function (moment, amMoment, angularMomentConfig) {\n\t\t\t\tfunction amDifferenceFilter(value, otherValue, unit, usePrecision, preprocessValue, preprocessOtherValue) {\n\t\t\t\t\tif (typeof value === 'undefined' || value === null) {\n\t\t\t\t\t\treturn '';\n\t\t\t\t\t}\n\n\t\t\t\t\tvalue = amMoment.preprocessDate(value, preprocessValue);\n\t\t\t\t\tvar date = moment(value);\n\t\t\t\t\tif (!date.isValid()) {\n\t\t\t\t\t\treturn '';\n\t\t\t\t\t}\n\n\t\t\t\t\tvar date2;\n\t\t\t\t\tif (typeof otherValue === 'undefined' || otherValue === null) {\n\t\t\t\t\t\tdate2 = moment();\n\t\t\t\t\t} else {\n\t\t\t\t\t\totherValue = amMoment.preprocessDate(otherValue, preprocessOtherValue);\n\t\t\t\t\t\tdate2 = moment(otherValue);\n\t\t\t\t\t\tif (!date2.isValid()) {\n\t\t\t\t\t\t\treturn '';\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn amMoment.applyTimezone(date).diff(amMoment.applyTimezone(date2), unit, usePrecision);\n\t\t\t\t}\n\n\t\t\t\tamDifferenceFilter.$stateful = angularMomentConfig.statefulFilters;\n\n\t\t\t\treturn amDifferenceFilter;\n\t\t\t}])\n\n\t\t/**\n\t\t * @ngdoc filter\n\t\t * @name angularMoment.filter:amDateFormat\n\t\t * @module angularMoment\n\t\t * @function\n\t\t */\n\t\t\t.filter('amDateFormat', ['moment', 'amMoment', 'angularMomentConfig', function (moment, amMoment, angularMomentConfig) {\n\t\t\t\tfunction amDateFormatFilter(value, format, preprocess, timezone, inputFormat) {\n\t\t\t\t\tvar currentFormat = inputFormat || angularMomentConfig.format;\n\t\t\t\t\tif (typeof value === 'undefined' || value === null) {\n\t\t\t\t\t\treturn '';\n\t\t\t\t\t}\n\n\t\t\t\t\tvalue = amMoment.preprocessDate(value, preprocess, currentFormat);\n\t\t\t\t\tvar date = moment(value);\n\t\t\t\t\tif (!date.isValid()) {\n\t\t\t\t\t\treturn '';\n\t\t\t\t\t}\n\n\t\t\t\t\treturn amMoment.applyTimezone(date, timezone).format(format);\n\t\t\t\t}\n\n\t\t\t\tamDateFormatFilter.$stateful = angularMomentConfig.statefulFilters;\n\n\t\t\t\treturn amDateFormatFilter;\n\t\t\t}])\n\n\t\t/**\n\t\t * @ngdoc filter\n\t\t * @name angularMoment.filter:amDurationFormat\n\t\t * @module angularMoment\n\t\t * @function\n\t\t */\n\t\t\t.filter('amDurationFormat', ['moment', 'angularMomentConfig', function (moment, angularMomentConfig) {\n\t\t\t\tfunction amDurationFormatFilter(value, format, suffix) {\n\t\t\t\t\tif (typeof value === 'undefined' || value === null) {\n\t\t\t\t\t\treturn '';\n\t\t\t\t\t}\n\n\t\t\t\t\treturn moment.duration(value, format).humanize(suffix);\n\t\t\t\t}\n\n\t\t\t\tamDurationFormatFilter.$stateful = angularMomentConfig.statefulFilters;\n\n\t\t\t\treturn amDurationFormatFilter;\n\t\t\t}])\n\n\t\t/**\n\t\t * @ngdoc filter\n\t\t * @name angularMoment.filter:amTimeAgo\n\t\t * @module angularMoment\n\t\t * @function\n\t\t */\n\t\t\t.filter('amTimeAgo', ['moment', 'amMoment', 'angularMomentConfig', function (moment, amMoment, angularMomentConfig) {\n\t\t\t\tfunction amTimeAgoFilter(value, preprocess, suffix, from) {\n\t\t\t\t\tvar date, dateFrom;\n\n\t\t\t\t\tif (typeof value === 'undefined' || value === null) {\n\t\t\t\t\t\treturn '';\n\t\t\t\t\t}\n\n\t\t\t\t\tvalue = amMoment.preprocessDate(value, preprocess);\n\t\t\t\t\tdate = moment(value);\n\t\t\t\t\tif (!date.isValid()) {\n\t\t\t\t\t\treturn '';\n\t\t\t\t\t}\n\n\t\t\t\t\tdateFrom = moment(from);\n\t\t\t\t\tif (typeof from !== 'undefined' && dateFrom.isValid()) {\n\t\t\t\t\t\treturn amMoment.applyTimezone(date).from(dateFrom, suffix);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn amMoment.applyTimezone(date).fromNow(suffix);\n\t\t\t\t}\n\n\t\t\t\tamTimeAgoFilter.$stateful = angularMomentConfig.statefulFilters;\n\n\t\t\t\treturn amTimeAgoFilter;\n\t\t\t}])\n\n\t\t/**\n\t\t * @ngdoc filter\n\t\t * @name angularMoment.filter:amSubtract\n\t\t * @module angularMoment\n\t\t * @function\n\t\t */\n\t\t\t.filter('amSubtract', ['moment', 'angularMomentConfig', function (moment, angularMomentConfig) {\n\t\t\t\tfunction amSubtractFilter(value, amount, type) {\n\n\t\t\t\t\tif (typeof value === 'undefined' || value === null) {\n\t\t\t\t\t\treturn '';\n\t\t\t\t\t}\n\n\t\t\t\t\treturn moment(value).subtract(parseInt(amount, 10), type);\n\t\t\t\t}\n\n\t\t\t\tamSubtractFilter.$stateful = angularMomentConfig.statefulFilters;\n\n\t\t\t\treturn amSubtractFilter;\n\t\t\t}])\n\n\t\t/**\n\t\t * @ngdoc filter\n\t\t * @name angularMoment.filter:amAdd\n\t\t * @module angularMoment\n\t\t * @function\n\t\t */\n\t\t\t.filter('amAdd', ['moment', 'angularMomentConfig', function (moment, angularMomentConfig) {\n\t\t\t\tfunction amAddFilter(value, amount, type) {\n\n\t\t\t\t\tif (typeof value === 'undefined' || value === null) {\n\t\t\t\t\t\treturn '';\n\t\t\t\t\t}\n\n\t\t\t\t\treturn moment(value).add(parseInt(amount, 10), type);\n\t\t\t\t}\n\n\t\t\t\tamAddFilter.$stateful = angularMomentConfig.statefulFilters;\n\n\t\t\t\treturn amAddFilter;\n\t\t\t}]);\n\t}\n\n\tif (typeof define === 'function' && define.amd) {\n\t\tdefine(['angular', 'moment'], angularMoment);\n\t} else if (typeof module !== 'undefined' && module && module.exports) {\n\t\tangularMoment(angular, require('moment'));\n\t\tmodule.exports = 'angularMoment';\n\t} else {\n\t\tangularMoment(angular, (typeof global !== 'undefined' ? global : window).moment);\n\t}\n})();\n\n(function (root, factory) {\r\n 'use strict';\r\n\r\n if (typeof define === 'function' && define.amd) {\r\n define(['angular'], factory);\r\n } else if (root.hasOwnProperty('angular')) {\r\n // Browser globals (root is window), we don't register it.\r\n factory(root.angular);\r\n } else if (typeof exports === 'object') {\r\n module.exports = factory(require('angular'));\r\n }\r\n}(this , function (angular) {\r\n 'use strict';\r\n\r\n // In cases where Angular does not get passed or angular is a truthy value\r\n // but misses .module we can fall back to using window.\r\n angular = (angular && angular.module ) ? angular : window.angular;\r\n\r\n\r\n function isStorageSupported($window, storageType) {\r\n\r\n // Some installations of IE, for an unknown reason, throw \"SCRIPT5: Error: Access is denied\"\r\n // when accessing window.localStorage. This happens before you try to do anything with it. Catch\r\n // that error and allow execution to continue.\r\n\r\n // fix 'SecurityError: DOM Exception 18' exception in Desktop Safari, Mobile Safari\r\n // when \"Block cookies\": \"Always block\" is turned on\r\n var supported;\r\n try {\r\n supported = $window[storageType];\r\n }\r\n catch(err) {\r\n supported = false;\r\n }\r\n\r\n // When Safari (OS X or iOS) is in private browsing mode, it appears as though localStorage and sessionStorage\r\n // is available, but trying to call .setItem throws an exception below:\r\n // \"QUOTA_EXCEEDED_ERR: DOM Exception 22: An attempt was made to add something to storage that exceeded the quota.\"\r\n if(supported) {\r\n var key = '__' + Math.round(Math.random() * 1e7);\r\n try {\r\n $window[storageType].setItem(key, key);\r\n $window[storageType].removeItem(key, key);\r\n }\r\n catch(err) {\r\n supported = false;\r\n }\r\n }\r\n\r\n return supported;\r\n }\r\n\r\n /**\r\n * @ngdoc overview\r\n * @name ngStorage\r\n */\r\n\r\n return angular.module('ngStorage', [])\r\n\r\n /**\r\n * @ngdoc object\r\n * @name ngStorage.$localStorage\r\n * @requires $rootScope\r\n * @requires $window\r\n */\r\n\r\n .provider('$localStorage', _storageProvider('localStorage'))\r\n\r\n /**\r\n * @ngdoc object\r\n * @name ngStorage.$sessionStorage\r\n * @requires $rootScope\r\n * @requires $window\r\n */\r\n\r\n .provider('$sessionStorage', _storageProvider('sessionStorage'));\r\n\r\n function _storageProvider(storageType) {\r\n var providerWebStorage = isStorageSupported(window, storageType);\r\n\r\n return function () {\r\n var storageKeyPrefix = 'ngStorage-';\r\n\r\n this.setKeyPrefix = function (prefix) {\r\n if (typeof prefix !== 'string') {\r\n throw new TypeError('[ngStorage] - ' + storageType + 'Provider.setKeyPrefix() expects a String.');\r\n }\r\n storageKeyPrefix = prefix;\r\n };\r\n\r\n var serializer = angular.toJson;\r\n var deserializer = angular.fromJson;\r\n\r\n this.setSerializer = function (s) {\r\n if (typeof s !== 'function') {\r\n throw new TypeError('[ngStorage] - ' + storageType + 'Provider.setSerializer expects a function.');\r\n }\r\n\r\n serializer = s;\r\n };\r\n\r\n this.setDeserializer = function (d) {\r\n if (typeof d !== 'function') {\r\n throw new TypeError('[ngStorage] - ' + storageType + 'Provider.setDeserializer expects a function.');\r\n }\r\n\r\n deserializer = d;\r\n };\r\n\r\n this.supported = function() {\r\n return !!providerWebStorage;\r\n };\r\n\r\n // Note: This is not very elegant at all.\r\n this.get = function (key) {\r\n return providerWebStorage && deserializer(providerWebStorage.getItem(storageKeyPrefix + key));\r\n };\r\n\r\n // Note: This is not very elegant at all.\r\n this.set = function (key, value) {\r\n return providerWebStorage && providerWebStorage.setItem(storageKeyPrefix + key, serializer(value));\r\n };\r\n\r\n this.remove = function (key) {\r\n providerWebStorage && providerWebStorage.removeItem(storageKeyPrefix + key);\r\n }\r\n\r\n this.$get = [\r\n '$rootScope',\r\n '$window',\r\n '$log',\r\n '$timeout',\r\n '$document',\r\n\r\n function(\r\n $rootScope,\r\n $window,\r\n $log,\r\n $timeout,\r\n $document\r\n ){\r\n\r\n // The magic number 10 is used which only works for some keyPrefixes...\r\n // See https://github.com/gsklee/ngStorage/issues/137\r\n var prefixLength = storageKeyPrefix.length;\r\n\r\n // #9: Assign a placeholder object if Web Storage is unavailable to prevent breaking the entire AngularJS app\r\n // Note: recheck mainly for testing (so we can use $window[storageType] rather than window[storageType])\r\n var isSupported = isStorageSupported($window, storageType),\r\n webStorage = isSupported || ($log.warn('This browser does not support Web Storage!'), {setItem: angular.noop, getItem: angular.noop, removeItem: angular.noop}),\r\n $storage = {\r\n $default: function(items) {\r\n for (var k in items) {\r\n angular.isDefined($storage[k]) || ($storage[k] = angular.copy(items[k]) );\r\n }\r\n\r\n $storage.$sync();\r\n return $storage;\r\n },\r\n $reset: function(items) {\r\n for (var k in $storage) {\r\n '$' === k[0] || (delete $storage[k] && webStorage.removeItem(storageKeyPrefix + k));\r\n }\r\n\r\n return $storage.$default(items);\r\n },\r\n $sync: function () {\r\n for (var i = 0, l = webStorage.length, k; i < l; i++) {\r\n // #8, #10: `webStorage.key(i)` may be an empty string (or throw an exception in IE9 if `webStorage` is empty)\r\n (k = webStorage.key(i)) && storageKeyPrefix === k.slice(0, prefixLength) && ($storage[k.slice(prefixLength)] = deserializer(webStorage.getItem(k)));\r\n }\r\n },\r\n $apply: function() {\r\n var temp$storage;\r\n\r\n _debounce = null;\r\n\r\n if (!angular.equals($storage, _last$storage)) {\r\n temp$storage = angular.copy(_last$storage);\r\n angular.forEach($storage, function(v, k) {\r\n if (angular.isDefined(v) && '$' !== k[0]) {\r\n webStorage.setItem(storageKeyPrefix + k, serializer(v));\r\n delete temp$storage[k];\r\n }\r\n });\r\n\r\n for (var k in temp$storage) {\r\n webStorage.removeItem(storageKeyPrefix + k);\r\n }\r\n\r\n _last$storage = angular.copy($storage);\r\n }\r\n },\r\n $supported: function() {\r\n return !!isSupported;\r\n }\r\n },\r\n _last$storage,\r\n _debounce;\r\n\r\n $storage.$sync();\r\n\r\n _last$storage = angular.copy($storage);\r\n\r\n $rootScope.$watch(function() {\r\n _debounce || (_debounce = $timeout($storage.$apply, 100, false));\r\n });\r\n\r\n // #6: Use `$window.addEventListener` instead of `angular.element` to avoid the jQuery-specific `event.originalEvent`\r\n $window.addEventListener && $window.addEventListener('storage', function(event) {\r\n if (!event.key) {\r\n return;\r\n }\r\n\r\n // Reference doc.\r\n var doc = $document[0];\r\n\r\n if ( (!doc.hasFocus || !doc.hasFocus()) && storageKeyPrefix === event.key.slice(0, prefixLength) ) {\r\n event.newValue ? $storage[event.key.slice(prefixLength)] = deserializer(event.newValue) : delete $storage[event.key.slice(prefixLength)];\r\n\r\n _last$storage = angular.copy($storage);\r\n\r\n $rootScope.$apply();\r\n }\r\n });\r\n\r\n $window.addEventListener && $window.addEventListener('beforeunload', function() {\r\n $storage.$apply();\r\n });\r\n\r\n return $storage;\r\n }\r\n ];\r\n };\r\n }\r\n\r\n}));\r\n\n// credits to vkbeautify (https://code.google.com/p/vkbeautify/)\n(function (factory) {\n if (typeof define === 'function' && define.amd) {\n return define(['angular'], function (angular) {\n return factory(angular);\n });\n } else if (typeof exports === 'object') {\n return module.exports = factory(require('angular')).name;\n } else {\n return factory(angular);\n }\n})(function (angular) {\n function createShiftArr (step) {\n var space = '';\n if (isNaN(parseInt(step))) // argument is string\n space = step;\n else // argument is integer\n for (var i = 0; i < step; i++)\n space += ' ';\n\n var shift = ['\\n']; // array of shifts\n\n for (var ix = 0; ix < 100; ix++)\n shift.push(shift[ix] + space);\n\n return shift;\n }\n\n function prettify (xml, indent) {\n if (isFinite(indent)) {\n if (indent !== 0)\n indent = indent || 2;\n } else if (!angular.isString(indent))\n indent = 2;\n\n var arr = xml.replace(/>\\s*<')\n .replace(/ or //\n if (arr[i].indexOf('-->') !== -1 || arr[i].indexOf(']>') !== -1 ||\n arr[i].indexOf('!DOCTYPE') !== -1) {\n inComment = false;\n }\n } else if (arr[i].indexOf('-->') !== -1 || arr[i].indexOf(']>') !== -1) { // end comment or //\n string += arr[i];\n inComment = false;\n } else if (/^<\\w/.test(arr[i - 1]) && /^<\\/\\w/.test(arr[i]) && //
//\n /^<[\\w:\\-\\.,]+/.exec(arr[i - 1]) == /^<\\/[\\w:\\-\\.,]+/.exec(arr[i])[0].replace('/', '')) { // fixme WTF?\n string += arr[i];\n if (!inComment) depth--;\n } else if (arr[i].search(/<\\w/) !== -1 && arr[i].indexOf('') === -1 && arr[i].indexOf('/>') === -1) //
//\n string += !inComment ? (shift[depth++] + arr[i]) : arr[i];\n else if (arr[i].search(/<\\w/) !== -1 && arr[i].indexOf('') !== -1) // ... //\n string += !inComment ? shift[depth] + arr[i] : arr[i];\n else if (arr[i].search(/<\\//) > -1) // //\n string += !inComment ? shift[--depth] + arr[i] : arr[i];\n else if (arr[i].indexOf('/>') !== -1) //
//\n string += !inComment ? shift[depth] + arr[i] : arr[i];\n else if (arr[i].indexOf('') !== -1) // xml ... ?> //\n string += shift[depth] + arr[i];\n else if (arr[i].indexOf('xmlns:') !== -1 || arr[i].indexOf('xmlns=') !== -1) // xmlns //\n string += shift[depth] + arr[i];\n else\n string += arr[i];\n }\n\n return string.trim();\n }\n\n return angular.module('prettyXml', [])\n .filter('prettyXml', function () {\n return prettify;\n });\n});\n/* ========================================================================\n * bootstrap-switch - v3.3.2\n * http://www.bootstrap-switch.org\n * ========================================================================\n * Copyright 2012-2013 Mattia Larentis\n *\n * ========================================================================\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ========================================================================\n */\n\n(function() {\n var __slice = [].slice;\n\n (function($, window) {\n \"use strict\";\n var BootstrapSwitch;\n BootstrapSwitch = (function() {\n function BootstrapSwitch(element, options) {\n if (options == null) {\n options = {};\n }\n this.$element = $(element);\n this.options = $.extend({}, $.fn.bootstrapSwitch.defaults, {\n state: this.$element.is(\":checked\"),\n size: this.$element.data(\"size\"),\n animate: this.$element.data(\"animate\"),\n disabled: this.$element.is(\":disabled\"),\n readonly: this.$element.is(\"[readonly]\"),\n indeterminate: this.$element.data(\"indeterminate\"),\n inverse: this.$element.data(\"inverse\"),\n radioAllOff: this.$element.data(\"radio-all-off\"),\n onColor: this.$element.data(\"on-color\"),\n offColor: this.$element.data(\"off-color\"),\n onText: this.$element.data(\"on-text\"),\n offText: this.$element.data(\"off-text\"),\n labelText: this.$element.data(\"label-text\"),\n handleWidth: this.$element.data(\"handle-width\"),\n labelWidth: this.$element.data(\"label-width\"),\n baseClass: this.$element.data(\"base-class\"),\n wrapperClass: this.$element.data(\"wrapper-class\")\n }, options);\n this.$wrapper = $(\"
\", {\n \"class\": (function(_this) {\n return function() {\n var classes;\n classes = [\"\" + _this.options.baseClass].concat(_this._getClasses(_this.options.wrapperClass));\n classes.push(_this.options.state ? \"\" + _this.options.baseClass + \"-on\" : \"\" + _this.options.baseClass + \"-off\");\n if (_this.options.size != null) {\n classes.push(\"\" + _this.options.baseClass + \"-\" + _this.options.size);\n }\n if (_this.options.disabled) {\n classes.push(\"\" + _this.options.baseClass + \"-disabled\");\n }\n if (_this.options.readonly) {\n classes.push(\"\" + _this.options.baseClass + \"-readonly\");\n }\n if (_this.options.indeterminate) {\n classes.push(\"\" + _this.options.baseClass + \"-indeterminate\");\n }\n if (_this.options.inverse) {\n classes.push(\"\" + _this.options.baseClass + \"-inverse\");\n }\n if (_this.$element.attr(\"id\")) {\n classes.push(\"\" + _this.options.baseClass + \"-id-\" + (_this.$element.attr(\"id\")));\n }\n return classes.join(\" \");\n };\n })(this)()\n });\n this.$container = $(\"
\", {\n \"class\": \"\" + this.options.baseClass + \"-container\"\n });\n this.$on = $(\"\", {\n html: this.options.onText,\n \"class\": \"\" + this.options.baseClass + \"-handle-on \" + this.options.baseClass + \"-\" + this.options.onColor\n });\n this.$off = $(\"\", {\n html: this.options.offText,\n \"class\": \"\" + this.options.baseClass + \"-handle-off \" + this.options.baseClass + \"-\" + this.options.offColor\n });\n this.$label = $(\"\", {\n html: this.options.labelText,\n \"class\": \"\" + this.options.baseClass + \"-label\"\n });\n this.$element.on(\"init.bootstrapSwitch\", (function(_this) {\n return function() {\n return _this.options.onInit.apply(element, arguments);\n };\n })(this));\n this.$element.on(\"switchChange.bootstrapSwitch\", (function(_this) {\n return function() {\n return _this.options.onSwitchChange.apply(element, arguments);\n };\n })(this));\n this.$container = this.$element.wrap(this.$container).parent();\n this.$wrapper = this.$container.wrap(this.$wrapper).parent();\n this.$element.before(this.options.inverse ? this.$off : this.$on).before(this.$label).before(this.options.inverse ? this.$on : this.$off);\n if (this.options.indeterminate) {\n this.$element.prop(\"indeterminate\", true);\n }\n this._init();\n this._elementHandlers();\n this._handleHandlers();\n this._labelHandlers();\n this._formHandler();\n this._externalLabelHandler();\n this.$element.trigger(\"init.bootstrapSwitch\");\n }\n\n BootstrapSwitch.prototype._constructor = BootstrapSwitch;\n\n BootstrapSwitch.prototype.state = function(value, skip) {\n if (typeof value === \"undefined\") {\n return this.options.state;\n }\n if (this.options.disabled || this.options.readonly) {\n return this.$element;\n }\n if (this.options.state && !this.options.radioAllOff && this.$element.is(\":radio\")) {\n return this.$element;\n }\n if (this.options.indeterminate) {\n this.indeterminate(false);\n }\n value = !!value;\n this.$element.prop(\"checked\", value).trigger(\"change.bootstrapSwitch\", skip);\n return this.$element;\n };\n\n BootstrapSwitch.prototype.toggleState = function(skip) {\n if (this.options.disabled || this.options.readonly) {\n return this.$element;\n }\n if (this.options.indeterminate) {\n this.indeterminate(false);\n return this.state(true);\n } else {\n return this.$element.prop(\"checked\", !this.options.state).trigger(\"change.bootstrapSwitch\", skip);\n }\n };\n\n BootstrapSwitch.prototype.size = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.size;\n }\n if (this.options.size != null) {\n this.$wrapper.removeClass(\"\" + this.options.baseClass + \"-\" + this.options.size);\n }\n if (value) {\n this.$wrapper.addClass(\"\" + this.options.baseClass + \"-\" + value);\n }\n this._width();\n this._containerPosition();\n this.options.size = value;\n return this.$element;\n };\n\n BootstrapSwitch.prototype.animate = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.animate;\n }\n value = !!value;\n if (value === this.options.animate) {\n return this.$element;\n }\n return this.toggleAnimate();\n };\n\n BootstrapSwitch.prototype.toggleAnimate = function() {\n this.options.animate = !this.options.animate;\n this.$wrapper.toggleClass(\"\" + this.options.baseClass + \"-animate\");\n return this.$element;\n };\n\n BootstrapSwitch.prototype.disabled = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.disabled;\n }\n value = !!value;\n if (value === this.options.disabled) {\n return this.$element;\n }\n return this.toggleDisabled();\n };\n\n BootstrapSwitch.prototype.toggleDisabled = function() {\n this.options.disabled = !this.options.disabled;\n this.$element.prop(\"disabled\", this.options.disabled);\n this.$wrapper.toggleClass(\"\" + this.options.baseClass + \"-disabled\");\n return this.$element;\n };\n\n BootstrapSwitch.prototype.readonly = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.readonly;\n }\n value = !!value;\n if (value === this.options.readonly) {\n return this.$element;\n }\n return this.toggleReadonly();\n };\n\n BootstrapSwitch.prototype.toggleReadonly = function() {\n this.options.readonly = !this.options.readonly;\n this.$element.prop(\"readonly\", this.options.readonly);\n this.$wrapper.toggleClass(\"\" + this.options.baseClass + \"-readonly\");\n return this.$element;\n };\n\n BootstrapSwitch.prototype.indeterminate = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.indeterminate;\n }\n value = !!value;\n if (value === this.options.indeterminate) {\n return this.$element;\n }\n return this.toggleIndeterminate();\n };\n\n BootstrapSwitch.prototype.toggleIndeterminate = function() {\n this.options.indeterminate = !this.options.indeterminate;\n this.$element.prop(\"indeterminate\", this.options.indeterminate);\n this.$wrapper.toggleClass(\"\" + this.options.baseClass + \"-indeterminate\");\n this._containerPosition();\n return this.$element;\n };\n\n BootstrapSwitch.prototype.inverse = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.inverse;\n }\n value = !!value;\n if (value === this.options.inverse) {\n return this.$element;\n }\n return this.toggleInverse();\n };\n\n BootstrapSwitch.prototype.toggleInverse = function() {\n var $off, $on;\n this.$wrapper.toggleClass(\"\" + this.options.baseClass + \"-inverse\");\n $on = this.$on.clone(true);\n $off = this.$off.clone(true);\n this.$on.replaceWith($off);\n this.$off.replaceWith($on);\n this.$on = $off;\n this.$off = $on;\n this.options.inverse = !this.options.inverse;\n return this.$element;\n };\n\n BootstrapSwitch.prototype.onColor = function(value) {\n var color;\n color = this.options.onColor;\n if (typeof value === \"undefined\") {\n return color;\n }\n if (color != null) {\n this.$on.removeClass(\"\" + this.options.baseClass + \"-\" + color);\n }\n this.$on.addClass(\"\" + this.options.baseClass + \"-\" + value);\n this.options.onColor = value;\n return this.$element;\n };\n\n BootstrapSwitch.prototype.offColor = function(value) {\n var color;\n color = this.options.offColor;\n if (typeof value === \"undefined\") {\n return color;\n }\n if (color != null) {\n this.$off.removeClass(\"\" + this.options.baseClass + \"-\" + color);\n }\n this.$off.addClass(\"\" + this.options.baseClass + \"-\" + value);\n this.options.offColor = value;\n return this.$element;\n };\n\n BootstrapSwitch.prototype.onText = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.onText;\n }\n this.$on.html(value);\n this._width();\n this._containerPosition();\n this.options.onText = value;\n return this.$element;\n };\n\n BootstrapSwitch.prototype.offText = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.offText;\n }\n this.$off.html(value);\n this._width();\n this._containerPosition();\n this.options.offText = value;\n return this.$element;\n };\n\n BootstrapSwitch.prototype.labelText = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.labelText;\n }\n this.$label.html(value);\n this._width();\n this.options.labelText = value;\n return this.$element;\n };\n\n BootstrapSwitch.prototype.handleWidth = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.handleWidth;\n }\n this.options.handleWidth = value;\n this._width();\n this._containerPosition();\n return this.$element;\n };\n\n BootstrapSwitch.prototype.labelWidth = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.labelWidth;\n }\n this.options.labelWidth = value;\n this._width();\n this._containerPosition();\n return this.$element;\n };\n\n BootstrapSwitch.prototype.baseClass = function(value) {\n return this.options.baseClass;\n };\n\n BootstrapSwitch.prototype.wrapperClass = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.wrapperClass;\n }\n if (!value) {\n value = $.fn.bootstrapSwitch.defaults.wrapperClass;\n }\n this.$wrapper.removeClass(this._getClasses(this.options.wrapperClass).join(\" \"));\n this.$wrapper.addClass(this._getClasses(value).join(\" \"));\n this.options.wrapperClass = value;\n return this.$element;\n };\n\n BootstrapSwitch.prototype.radioAllOff = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.radioAllOff;\n }\n value = !!value;\n if (value === this.options.radioAllOff) {\n return this.$element;\n }\n this.options.radioAllOff = value;\n return this.$element;\n };\n\n BootstrapSwitch.prototype.onInit = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.onInit;\n }\n if (!value) {\n value = $.fn.bootstrapSwitch.defaults.onInit;\n }\n this.options.onInit = value;\n return this.$element;\n };\n\n BootstrapSwitch.prototype.onSwitchChange = function(value) {\n if (typeof value === \"undefined\") {\n return this.options.onSwitchChange;\n }\n if (!value) {\n value = $.fn.bootstrapSwitch.defaults.onSwitchChange;\n }\n this.options.onSwitchChange = value;\n return this.$element;\n };\n\n BootstrapSwitch.prototype.destroy = function() {\n var $form;\n $form = this.$element.closest(\"form\");\n if ($form.length) {\n $form.off(\"reset.bootstrapSwitch\").removeData(\"bootstrap-switch\");\n }\n this.$container.children().not(this.$element).remove();\n this.$element.unwrap().unwrap().off(\".bootstrapSwitch\").removeData(\"bootstrap-switch\");\n return this.$element;\n };\n\n BootstrapSwitch.prototype._width = function() {\n var $handles, handleWidth;\n $handles = this.$on.add(this.$off);\n $handles.add(this.$label).css(\"width\", \"\");\n handleWidth = this.options.handleWidth === \"auto\" ? Math.max(this.$on.width(), this.$off.width()) : this.options.handleWidth;\n $handles.width(handleWidth);\n this.$label.width((function(_this) {\n return function(index, width) {\n if (_this.options.labelWidth !== \"auto\") {\n return _this.options.labelWidth;\n }\n if (width < handleWidth) {\n return handleWidth;\n } else {\n return width;\n }\n };\n })(this));\n this._handleWidth = this.$on.outerWidth();\n this._labelWidth = this.$label.outerWidth();\n this.$container.width((this._handleWidth * 2) + this._labelWidth);\n return this.$wrapper.width(this._handleWidth + this._labelWidth);\n };\n\n BootstrapSwitch.prototype._containerPosition = function(state, callback) {\n if (state == null) {\n state = this.options.state;\n }\n this.$container.css(\"margin-left\", (function(_this) {\n return function() {\n var values;\n values = [0, \"-\" + _this._handleWidth + \"px\"];\n if (_this.options.indeterminate) {\n return \"-\" + (_this._handleWidth / 2) + \"px\";\n }\n if (state) {\n if (_this.options.inverse) {\n return values[1];\n } else {\n return values[0];\n }\n } else {\n if (_this.options.inverse) {\n return values[0];\n } else {\n return values[1];\n }\n }\n };\n })(this));\n if (!callback) {\n return;\n }\n return setTimeout(function() {\n return callback();\n }, 50);\n };\n\n BootstrapSwitch.prototype._init = function() {\n var init, initInterval;\n init = (function(_this) {\n return function() {\n _this._width();\n return _this._containerPosition(null, function() {\n if (_this.options.animate) {\n return _this.$wrapper.addClass(\"\" + _this.options.baseClass + \"-animate\");\n }\n });\n };\n })(this);\n if (this.$wrapper.is(\":visible\")) {\n return init();\n }\n return initInterval = window.setInterval((function(_this) {\n return function() {\n if (_this.$wrapper.is(\":visible\")) {\n init();\n return window.clearInterval(initInterval);\n }\n };\n })(this), 50);\n };\n\n BootstrapSwitch.prototype._elementHandlers = function() {\n return this.$element.on({\n \"change.bootstrapSwitch\": (function(_this) {\n return function(e, skip) {\n var state;\n e.preventDefault();\n e.stopImmediatePropagation();\n state = _this.$element.is(\":checked\");\n _this._containerPosition(state);\n if (state === _this.options.state) {\n return;\n }\n _this.options.state = state;\n _this.$wrapper.toggleClass(\"\" + _this.options.baseClass + \"-off\").toggleClass(\"\" + _this.options.baseClass + \"-on\");\n if (!skip) {\n if (_this.$element.is(\":radio\")) {\n $(\"[name='\" + (_this.$element.attr('name')) + \"']\").not(_this.$element).prop(\"checked\", false).trigger(\"change.bootstrapSwitch\", true);\n }\n return _this.$element.trigger(\"switchChange.bootstrapSwitch\", [state]);\n }\n };\n })(this),\n \"focus.bootstrapSwitch\": (function(_this) {\n return function(e) {\n e.preventDefault();\n return _this.$wrapper.addClass(\"\" + _this.options.baseClass + \"-focused\");\n };\n })(this),\n \"blur.bootstrapSwitch\": (function(_this) {\n return function(e) {\n e.preventDefault();\n return _this.$wrapper.removeClass(\"\" + _this.options.baseClass + \"-focused\");\n };\n })(this),\n \"keydown.bootstrapSwitch\": (function(_this) {\n return function(e) {\n if (!e.which || _this.options.disabled || _this.options.readonly) {\n return;\n }\n switch (e.which) {\n case 37:\n e.preventDefault();\n e.stopImmediatePropagation();\n return _this.state(false);\n case 39:\n e.preventDefault();\n e.stopImmediatePropagation();\n return _this.state(true);\n }\n };\n })(this)\n });\n };\n\n BootstrapSwitch.prototype._handleHandlers = function() {\n this.$on.on(\"click.bootstrapSwitch\", (function(_this) {\n return function(event) {\n event.preventDefault();\n event.stopPropagation();\n _this.state(false);\n return _this.$element.trigger(\"focus.bootstrapSwitch\");\n };\n })(this));\n return this.$off.on(\"click.bootstrapSwitch\", (function(_this) {\n return function(event) {\n event.preventDefault();\n event.stopPropagation();\n _this.state(true);\n return _this.$element.trigger(\"focus.bootstrapSwitch\");\n };\n })(this));\n };\n\n BootstrapSwitch.prototype._labelHandlers = function() {\n return this.$label.on({\n \"mousedown.bootstrapSwitch touchstart.bootstrapSwitch\": (function(_this) {\n return function(e) {\n if (_this._dragStart || _this.options.disabled || _this.options.readonly) {\n return;\n }\n e.preventDefault();\n e.stopPropagation();\n _this._dragStart = (e.pageX || e.originalEvent.touches[0].pageX) - parseInt(_this.$container.css(\"margin-left\"), 10);\n if (_this.options.animate) {\n _this.$wrapper.removeClass(\"\" + _this.options.baseClass + \"-animate\");\n }\n return _this.$element.trigger(\"focus.bootstrapSwitch\");\n };\n })(this),\n \"mousemove.bootstrapSwitch touchmove.bootstrapSwitch\": (function(_this) {\n return function(e) {\n var difference;\n if (_this._dragStart == null) {\n return;\n }\n e.preventDefault();\n difference = (e.pageX || e.originalEvent.touches[0].pageX) - _this._dragStart;\n if (difference < -_this._handleWidth || difference > 0) {\n return;\n }\n _this._dragEnd = difference;\n return _this.$container.css(\"margin-left\", \"\" + _this._dragEnd + \"px\");\n };\n })(this),\n \"mouseup.bootstrapSwitch touchend.bootstrapSwitch\": (function(_this) {\n return function(e) {\n var state;\n if (!_this._dragStart) {\n return;\n }\n e.preventDefault();\n if (_this.options.animate) {\n _this.$wrapper.addClass(\"\" + _this.options.baseClass + \"-animate\");\n }\n if (_this._dragEnd) {\n state = _this._dragEnd > -(_this._handleWidth / 2);\n _this._dragEnd = false;\n _this.state(_this.options.inverse ? !state : state);\n } else {\n _this.state(!_this.options.state);\n }\n return _this._dragStart = false;\n };\n })(this),\n \"mouseleave.bootstrapSwitch\": (function(_this) {\n return function(e) {\n return _this.$label.trigger(\"mouseup.bootstrapSwitch\");\n };\n })(this)\n });\n };\n\n BootstrapSwitch.prototype._externalLabelHandler = function() {\n var $externalLabel;\n $externalLabel = this.$element.closest(\"label\");\n return $externalLabel.on(\"click\", (function(_this) {\n return function(event) {\n event.preventDefault();\n event.stopImmediatePropagation();\n if (event.target === $externalLabel[0]) {\n return _this.toggleState();\n }\n };\n })(this));\n };\n\n BootstrapSwitch.prototype._formHandler = function() {\n var $form;\n $form = this.$element.closest(\"form\");\n if ($form.data(\"bootstrap-switch\")) {\n return;\n }\n return $form.on(\"reset.bootstrapSwitch\", function() {\n return window.setTimeout(function() {\n return $form.find(\"input\").filter(function() {\n return $(this).data(\"bootstrap-switch\");\n }).each(function() {\n return $(this).bootstrapSwitch(\"state\", this.checked);\n });\n }, 1);\n }).data(\"bootstrap-switch\", true);\n };\n\n BootstrapSwitch.prototype._getClasses = function(classes) {\n var c, cls, _i, _len;\n if (!$.isArray(classes)) {\n return [\"\" + this.options.baseClass + \"-\" + classes];\n }\n cls = [];\n for (_i = 0, _len = classes.length; _i < _len; _i++) {\n c = classes[_i];\n cls.push(\"\" + this.options.baseClass + \"-\" + c);\n }\n return cls;\n };\n\n return BootstrapSwitch;\n\n })();\n $.fn.bootstrapSwitch = function() {\n var args, option, ret;\n option = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];\n ret = this;\n this.each(function() {\n var $this, data;\n $this = $(this);\n data = $this.data(\"bootstrap-switch\");\n if (!data) {\n $this.data(\"bootstrap-switch\", data = new BootstrapSwitch(this, option));\n }\n if (typeof option === \"string\") {\n return ret = data[option].apply(data, args);\n }\n });\n return ret;\n };\n $.fn.bootstrapSwitch.Constructor = BootstrapSwitch;\n return $.fn.bootstrapSwitch.defaults = {\n state: true,\n size: null,\n animate: true,\n disabled: false,\n readonly: false,\n indeterminate: false,\n inverse: false,\n radioAllOff: false,\n onColor: \"primary\",\n offColor: \"default\",\n onText: \"ON\",\n offText: \"OFF\",\n labelText: \" \",\n handleWidth: \"auto\",\n labelWidth: \"auto\",\n baseClass: \"bootstrap-switch\",\n wrapperClass: \"wrapper\",\n onInit: function() {},\n onSwitchChange: function() {}\n };\n })(window.jQuery, window);\n\n}).call(this);\n\n/**\r\n * angular-bootstrap-switch\r\n * @version v0.4.1 - 2015-06-15\r\n * @author Francesco Pontillo (francescopontillo@gmail.com)\r\n * @link https://github.com/frapontillo/angular-bootstrap-switch\r\n * @license Apache License 2.0(http://www.apache.org/licenses/LICENSE-2.0.html)\r\n**/\r\n\r\n(function() {\r\n'use strict';\r\n\r\n// Source: common/module.js\r\nangular.module('frapontillo.bootstrap-switch', []);\r\n\r\n// Source: dist/.temp/directives/bsSwitch.js\r\nangular.module('frapontillo.bootstrap-switch').directive('bsSwitch', [\r\n '$parse',\r\n '$timeout',\r\n function ($parse, $timeout) {\r\n return {\r\n restrict: 'A',\r\n require: 'ngModel',\r\n link: function link(scope, element, attrs, controller) {\r\n var isInit = false;\r\n /**\r\n * Return the true value for this specific checkbox.\r\n * @returns {Object} representing the true view value; if undefined, returns true.\r\n */\r\n var getTrueValue = function () {\r\n if (attrs.type === 'radio') {\r\n return attrs.value || $parse(attrs.ngValue)(scope) || true;\r\n }\r\n var trueValue = $parse(attrs.ngTrueValue)(scope);\r\n if (angular.isUndefined(trueValue)) {\r\n trueValue = true;\r\n }\r\n return trueValue;\r\n };\r\n /**\r\n * Get a boolean value from a boolean-like string, evaluating it on the current scope.\r\n * @param value The input object\r\n * @returns {boolean} A boolean value\r\n */\r\n var getBooleanFromString = function (value) {\r\n return scope.$eval(value) === true;\r\n };\r\n /**\r\n * Get a boolean value from a boolean-like string, defaulting to true if undefined.\r\n * @param value The input object\r\n * @returns {boolean} A boolean value\r\n */\r\n var getBooleanFromStringDefTrue = function (value) {\r\n return value === true || value === 'true' || !value;\r\n };\r\n /**\r\n * Returns the value if it is truthy, or undefined.\r\n *\r\n * @param value The value to check.\r\n * @returns the original value if it is truthy, {@link undefined} otherwise.\r\n */\r\n var getValueOrUndefined = function (value) {\r\n return value ? value : undefined;\r\n };\r\n /**\r\n * Get the value of the angular-bound attribute, given its name.\r\n * The returned value may or may not equal the attribute value, as it may be transformed by a function.\r\n *\r\n * @param attrName The angular-bound attribute name to get the value for\r\n * @returns {*} The attribute value\r\n */\r\n var getSwitchAttrValue = function (attrName) {\r\n var map = {\r\n 'switchRadioOff': getBooleanFromStringDefTrue,\r\n 'switchActive': function (value) {\r\n return !getBooleanFromStringDefTrue(value);\r\n },\r\n 'switchAnimate': getBooleanFromStringDefTrue,\r\n 'switchLabel': function (value) {\r\n return value ? value : ' ';\r\n },\r\n 'switchIcon': function (value) {\r\n if (value) {\r\n return '';\r\n }\r\n },\r\n 'switchWrapper': function (value) {\r\n return value || 'wrapper';\r\n },\r\n 'switchInverse': getBooleanFromString,\r\n 'switchReadonly': getBooleanFromString\r\n };\r\n var transFn = map[attrName] || getValueOrUndefined;\r\n return transFn(attrs[attrName]);\r\n };\r\n /**\r\n * Set a bootstrapSwitch parameter according to the angular-bound attribute.\r\n * The parameter will be changed only if the switch has already been initialized\r\n * (to avoid creating it before the model is ready).\r\n *\r\n * @param element The switch to apply the parameter modification to\r\n * @param attr The name of the switch parameter\r\n * @param modelAttr The name of the angular-bound parameter\r\n */\r\n var setSwitchParamMaybe = function (element, attr, modelAttr) {\r\n if (!isInit) {\r\n return;\r\n }\r\n var newValue = getSwitchAttrValue(modelAttr);\r\n element.bootstrapSwitch(attr, newValue);\r\n };\r\n var setActive = function () {\r\n setSwitchParamMaybe(element, 'disabled', 'switchActive');\r\n };\r\n /**\r\n * If the directive has not been initialized yet, do so.\r\n */\r\n var initMaybe = function () {\r\n // if it's the first initialization\r\n if (!isInit) {\r\n var viewValue = controller.$modelValue === getTrueValue();\r\n isInit = !isInit;\r\n // Bootstrap the switch plugin\r\n element.bootstrapSwitch({\r\n radioAllOff: getSwitchAttrValue('switchRadioOff'),\r\n disabled: getSwitchAttrValue('switchActive'),\r\n state: viewValue,\r\n onText: getSwitchAttrValue('switchOnText'),\r\n offText: getSwitchAttrValue('switchOffText'),\r\n onColor: getSwitchAttrValue('switchOnColor'),\r\n offColor: getSwitchAttrValue('switchOffColor'),\r\n animate: getSwitchAttrValue('switchAnimate'),\r\n size: getSwitchAttrValue('switchSize'),\r\n labelText: attrs.switchLabel ? getSwitchAttrValue('switchLabel') : getSwitchAttrValue('switchIcon'),\r\n wrapperClass: getSwitchAttrValue('switchWrapper'),\r\n handleWidth: getSwitchAttrValue('switchHandleWidth'),\r\n labelWidth: getSwitchAttrValue('switchLabelWidth'),\r\n inverse: getSwitchAttrValue('switchInverse'),\r\n readonly: getSwitchAttrValue('switchReadonly')\r\n });\r\n if (attrs.type === 'radio') {\r\n controller.$setViewValue(controller.$modelValue);\r\n } else {\r\n controller.$setViewValue(viewValue);\r\n }\r\n }\r\n };\r\n /**\r\n * Listen to model changes.\r\n */\r\n var listenToModel = function () {\r\n attrs.$observe('switchActive', function (newValue) {\r\n var active = getBooleanFromStringDefTrue(newValue);\r\n // if we are disabling the switch, delay the deactivation so that the toggle can be switched\r\n if (!active) {\r\n $timeout(function () {\r\n setActive(active);\r\n });\r\n } else {\r\n // if we are enabling the switch, set active right away\r\n setActive(active);\r\n }\r\n });\r\n function modelValue() {\r\n return controller.$modelValue;\r\n }\r\n // When the model changes\r\n scope.$watch(modelValue, function (newValue) {\r\n initMaybe();\r\n if (newValue !== undefined) {\r\n element.bootstrapSwitch('state', newValue === getTrueValue(), false);\r\n } else {\r\n element.bootstrapSwitch('toggleIndeterminate', true, false);\r\n }\r\n }, true);\r\n // angular attribute to switch property bindings\r\n var bindings = {\r\n 'switchRadioOff': 'radioAllOff',\r\n 'switchOnText': 'onText',\r\n 'switchOffText': 'offText',\r\n 'switchOnColor': 'onColor',\r\n 'switchOffColor': 'offColor',\r\n 'switchAnimate': 'animate',\r\n 'switchSize': 'size',\r\n 'switchLabel': 'labelText',\r\n 'switchIcon': 'labelText',\r\n 'switchWrapper': 'wrapperClass',\r\n 'switchHandleWidth': 'handleWidth',\r\n 'switchLabelWidth': 'labelWidth',\r\n 'switchInverse': 'inverse',\r\n 'switchReadonly': 'readonly'\r\n };\r\n var observeProp = function (prop, bindings) {\r\n return function () {\r\n attrs.$observe(prop, function () {\r\n setSwitchParamMaybe(element, bindings[prop], prop);\r\n });\r\n };\r\n };\r\n // for every angular-bound attribute, observe it and trigger the appropriate switch function\r\n for (var prop in bindings) {\r\n attrs.$observe(prop, observeProp(prop, bindings));\r\n }\r\n };\r\n /**\r\n * Listen to view changes.\r\n */\r\n var listenToView = function () {\r\n if (attrs.type === 'radio') {\r\n // when the switch is clicked\r\n element.on('change.bootstrapSwitch', function (e) {\r\n // discard not real change events\r\n if (controller.$modelValue === controller.$viewValue && e.target.checked !== $(e.target).bootstrapSwitch('state')) {\r\n // $setViewValue --> $viewValue --> $parsers --> $modelValue\r\n // if the switch is indeed selected\r\n if (e.target.checked) {\r\n // set its value into the view\r\n controller.$setViewValue(getTrueValue());\r\n } else if (getTrueValue() === controller.$viewValue) {\r\n // otherwise if it's been deselected, delete the view value\r\n controller.$setViewValue(undefined);\r\n }\r\n }\r\n });\r\n } else {\r\n // When the checkbox switch is clicked, set its value into the ngModel\r\n element.on('switchChange.bootstrapSwitch', function (e) {\r\n // $setViewValue --> $viewValue --> $parsers --> $modelValue\r\n controller.$setViewValue(e.target.checked);\r\n });\r\n }\r\n };\r\n // Listen and respond to view changes\r\n listenToView();\r\n // Listen and respond to model changes\r\n listenToModel();\r\n // On destroy, collect ya garbage\r\n scope.$on('$destroy', function () {\r\n element.bootstrapSwitch('destroy');\r\n });\r\n }\r\n };\r\n }\r\n]).directive('bsSwitch', function () {\r\n return {\r\n restrict: 'E',\r\n require: 'ngModel',\r\n template: '',\r\n replace: true\r\n };\r\n});\r\n// Source: bsSwitch.suffix\r\n})();\nvar COMPILED = !0, goog = goog || {};\ngoog.global = this;\ngoog.isDef = function(a) {\n return void 0 !== a;\n};\ngoog.isString = function(a) {\n return \"string\" == typeof a;\n};\ngoog.isBoolean = function(a) {\n return \"boolean\" == typeof a;\n};\ngoog.isNumber = function(a) {\n return \"number\" == typeof a;\n};\ngoog.exportPath_ = function(a, b, c) {\n a = a.split(\".\");\n c = c || goog.global;\n a[0] in c || \"undefined\" == typeof c.execScript || c.execScript(\"var \" + a[0]);\n for (var d; a.length && (d = a.shift());) {\n !a.length && goog.isDef(b) ? c[d] = b : c = c[d] && c[d] !== Object.prototype[d] ? c[d] : c[d] = {};\n }\n};\ngoog.define = function(a, b) {\n var c = b;\n if (!COMPILED) {\n var d = goog.global.CLOSURE_UNCOMPILED_DEFINES, e = goog.global.CLOSURE_DEFINES;\n d && void 0 === d.nodeType && Object.prototype.hasOwnProperty.call(d, a) ? c = d[a] : e && void 0 === e.nodeType && Object.prototype.hasOwnProperty.call(e, a) && (c = e[a]);\n }\n goog.exportPath_(a, c);\n return c;\n};\ngoog.DEBUG = !0;\ngoog.LOCALE = \"en\";\ngoog.TRUSTED_SITE = !0;\ngoog.STRICT_MODE_COMPATIBLE = !1;\ngoog.DISALLOW_TEST_ONLY_CODE = COMPILED && !goog.DEBUG;\ngoog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING = !1;\ngoog.provide = function(a) {\n if (goog.isInModuleLoader_()) {\n throw Error(\"goog.provide cannot be used within a module.\");\n }\n if (!COMPILED && goog.isProvided_(a)) {\n throw Error('Namespace \"' + a + '\" already declared.');\n }\n goog.constructNamespace_(a);\n};\ngoog.constructNamespace_ = function(a, b) {\n if (!COMPILED) {\n delete goog.implicitNamespaces_[a];\n for (var c = a; (c = c.substring(0, c.lastIndexOf(\".\"))) && !goog.getObjectByName(c);) {\n goog.implicitNamespaces_[c] = !0;\n }\n }\n goog.exportPath_(a, b);\n};\ngoog.getScriptNonce = function(a) {\n if (a && a != goog.global) {\n return goog.getScriptNonce_(a.document);\n }\n null === goog.cspNonce_ && (goog.cspNonce_ = goog.getScriptNonce_(goog.global.document));\n return goog.cspNonce_;\n};\ngoog.NONCE_PATTERN_ = /^[\\w+/_-]+[=]{0,2}$/;\ngoog.cspNonce_ = null;\ngoog.getScriptNonce_ = function(a) {\n return (a = a.querySelector && a.querySelector(\"script[nonce]\")) && (a = a.nonce || a.getAttribute(\"nonce\")) && goog.NONCE_PATTERN_.test(a) ? a : \"\";\n};\ngoog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/;\ngoog.module = function(a) {\n if (!goog.isString(a) || !a || -1 == a.search(goog.VALID_MODULE_RE_)) {\n throw Error(\"Invalid module identifier\");\n }\n if (!goog.isInGoogModuleLoader_()) {\n throw Error(\"Module \" + a + \" has been loaded incorrectly. Note, modules cannot be loaded as normal scripts. They require some kind of pre-processing step. You're likely trying to load a module via a script tag or as a part of a concatenated bundle without rewriting the module. For more info see: https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide.\");\n }\n if (goog.moduleLoaderState_.moduleName) {\n throw Error(\"goog.module may only be called once per module.\");\n }\n goog.moduleLoaderState_.moduleName = a;\n if (!COMPILED) {\n if (goog.isProvided_(a)) {\n throw Error('Namespace \"' + a + '\" already declared.');\n }\n delete goog.implicitNamespaces_[a];\n }\n};\ngoog.module.get = function(a) {\n return goog.module.getInternal_(a);\n};\ngoog.module.getInternal_ = function(a) {\n if (!COMPILED) {\n if (a in goog.loadedModules_) {\n return goog.loadedModules_[a].exports;\n }\n if (!goog.implicitNamespaces_[a]) {\n return a = goog.getObjectByName(a), null != a ? a : null;\n }\n }\n return null;\n};\ngoog.ModuleType = {ES6:\"es6\", GOOG:\"goog\"};\ngoog.moduleLoaderState_ = null;\ngoog.isInModuleLoader_ = function() {\n return goog.isInGoogModuleLoader_() || goog.isInEs6ModuleLoader_();\n};\ngoog.isInGoogModuleLoader_ = function() {\n return !!goog.moduleLoaderState_ && goog.moduleLoaderState_.type == goog.ModuleType.GOOG;\n};\ngoog.isInEs6ModuleLoader_ = function() {\n if (goog.moduleLoaderState_ && goog.moduleLoaderState_.type == goog.ModuleType.ES6) {\n return !0;\n }\n var a = goog.global.$jscomp;\n return a ? \"function\" != typeof a.getCurrentModulePath ? !1 : !!a.getCurrentModulePath() : !1;\n};\ngoog.module.declareLegacyNamespace = function() {\n if (!COMPILED && !goog.isInGoogModuleLoader_()) {\n throw Error(\"goog.module.declareLegacyNamespace must be called from within a goog.module\");\n }\n if (!COMPILED && !goog.moduleLoaderState_.moduleName) {\n throw Error(\"goog.module must be called prior to goog.module.declareLegacyNamespace.\");\n }\n goog.moduleLoaderState_.declareLegacyNamespace = !0;\n};\ngoog.declareModuleId = function(a) {\n if (!COMPILED) {\n if (!goog.isInEs6ModuleLoader_()) {\n throw Error(\"goog.declareModuleId may only be called from within an ES6 module\");\n }\n if (goog.moduleLoaderState_ && goog.moduleLoaderState_.moduleName) {\n throw Error(\"goog.declareModuleId may only be called once per module.\");\n }\n if (a in goog.loadedModules_) {\n throw Error('Module with namespace \"' + a + '\" already exists.');\n }\n }\n if (goog.moduleLoaderState_) {\n goog.moduleLoaderState_.moduleName = a;\n } else {\n var b = goog.global.$jscomp;\n if (!b || \"function\" != typeof b.getCurrentModulePath) {\n throw Error('Module with namespace \"' + a + '\" has been loaded incorrectly.');\n }\n b = b.require(b.getCurrentModulePath());\n goog.loadedModules_[a] = {exports:b, type:goog.ModuleType.ES6, moduleId:a};\n }\n};\ngoog.module.declareNamespace = goog.declareModuleId;\ngoog.setTestOnly = function(a) {\n if (goog.DISALLOW_TEST_ONLY_CODE) {\n throw a = a || \"\", Error(\"Importing test-only code into non-debug environment\" + (a ? \": \" + a : \".\"));\n }\n};\ngoog.forwardDeclare = function(a) {\n};\nCOMPILED || (goog.isProvided_ = function(a) {\n return a in goog.loadedModules_ || !goog.implicitNamespaces_[a] && goog.isDefAndNotNull(goog.getObjectByName(a));\n}, goog.implicitNamespaces_ = {\"goog.module\":!0});\ngoog.getObjectByName = function(a, b) {\n for (var c = a.split(\".\"), d = b || goog.global, e = 0; e < c.length; e++) {\n if (d = d[c[e]], !goog.isDefAndNotNull(d)) {\n return null;\n }\n }\n return d;\n};\ngoog.globalize = function(a, b) {\n var c = b || goog.global, d;\n for (d in a) {\n c[d] = a[d];\n }\n};\ngoog.addDependency = function(a, b, c, d) {\n !COMPILED && goog.DEPENDENCIES_ENABLED && goog.debugLoader_.addDependency(a, b, c, d);\n};\ngoog.ENABLE_DEBUG_LOADER = !0;\ngoog.logToConsole_ = function(a) {\n goog.global.console && goog.global.console.error(a);\n};\ngoog.require = function(a) {\n if (!COMPILED) {\n goog.ENABLE_DEBUG_LOADER && goog.debugLoader_.requested(a);\n if (goog.isProvided_(a)) {\n if (goog.isInModuleLoader_()) {\n return goog.module.getInternal_(a);\n }\n } else {\n if (goog.ENABLE_DEBUG_LOADER) {\n var b = goog.moduleLoaderState_;\n goog.moduleLoaderState_ = null;\n try {\n goog.debugLoader_.load_(a);\n } finally {\n goog.moduleLoaderState_ = b;\n }\n }\n }\n return null;\n }\n};\ngoog.requireType = function(a) {\n return {};\n};\ngoog.basePath = \"\";\ngoog.nullFunction = function() {\n};\ngoog.abstractMethod = function() {\n throw Error(\"unimplemented abstract method\");\n};\ngoog.addSingletonGetter = function(a) {\n a.instance_ = void 0;\n a.getInstance = function() {\n if (a.instance_) {\n return a.instance_;\n }\n goog.DEBUG && (goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = a);\n return a.instance_ = new a;\n };\n};\ngoog.instantiatedSingletons_ = [];\ngoog.LOAD_MODULE_USING_EVAL = !0;\ngoog.SEAL_MODULE_EXPORTS = goog.DEBUG;\ngoog.loadedModules_ = {};\ngoog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;\ngoog.TRANSPILE = \"detect\";\ngoog.ASSUME_ES_MODULES_TRANSPILED = !1;\ngoog.TRANSPILE_TO_LANGUAGE = \"\";\ngoog.TRANSPILER = \"transpile.js\";\ngoog.hasBadLetScoping = null;\ngoog.useSafari10Workaround = function() {\n if (null == goog.hasBadLetScoping) {\n try {\n var a = !eval('\"use strict\";let x = 1; function f() { return typeof x; };f() == \"number\";');\n } catch (b) {\n a = !1;\n }\n goog.hasBadLetScoping = a;\n }\n return goog.hasBadLetScoping;\n};\ngoog.workaroundSafari10EvalBug = function(a) {\n return \"(function(){\" + a + \"\\n;})();\\n\";\n};\ngoog.loadModule = function(a) {\n var b = goog.moduleLoaderState_;\n try {\n goog.moduleLoaderState_ = {moduleName:\"\", declareLegacyNamespace:!1, type:goog.ModuleType.GOOG};\n if (goog.isFunction(a)) {\n var c = a.call(void 0, {});\n } else {\n if (goog.isString(a)) {\n goog.useSafari10Workaround() && (a = goog.workaroundSafari10EvalBug(a)), c = goog.loadModuleFromSource_.call(void 0, a);\n } else {\n throw Error(\"Invalid module definition\");\n }\n }\n var d = goog.moduleLoaderState_.moduleName;\n if (goog.isString(d) && d) {\n goog.moduleLoaderState_.declareLegacyNamespace ? goog.constructNamespace_(d, c) : goog.SEAL_MODULE_EXPORTS && Object.seal && \"object\" == typeof c && null != c && Object.seal(c), goog.loadedModules_[d] = {exports:c, type:goog.ModuleType.GOOG, moduleId:goog.moduleLoaderState_.moduleName};\n } else {\n throw Error('Invalid module name \"' + d + '\"');\n }\n } finally {\n goog.moduleLoaderState_ = b;\n }\n};\ngoog.loadModuleFromSource_ = function(a) {\n eval(a);\n return {};\n};\ngoog.normalizePath_ = function(a) {\n a = a.split(\"/\");\n for (var b = 0; b < a.length;) {\n \".\" == a[b] ? a.splice(b, 1) : b && \"..\" == a[b] && a[b - 1] && \"..\" != a[b - 1] ? a.splice(--b, 2) : b++;\n }\n return a.join(\"/\");\n};\ngoog.loadFileSync_ = function(a) {\n if (goog.global.CLOSURE_LOAD_FILE_SYNC) {\n return goog.global.CLOSURE_LOAD_FILE_SYNC(a);\n }\n try {\n var b = new goog.global.XMLHttpRequest;\n b.open(\"get\", a, !1);\n b.send();\n return 0 == b.status || 200 == b.status ? b.responseText : null;\n } catch (c) {\n return null;\n }\n};\ngoog.transpile_ = function(a, b, c) {\n var d = goog.global.$jscomp;\n d || (goog.global.$jscomp = d = {});\n var e = d.transpile;\n if (!e) {\n var f = goog.basePath + goog.TRANSPILER, g = goog.loadFileSync_(f);\n if (g) {\n (function() {\n eval(g + \"\\n//# sourceURL=\" + f);\n }).call(goog.global);\n if (goog.global.$gwtExport && goog.global.$gwtExport.$jscomp && !goog.global.$gwtExport.$jscomp.transpile) {\n throw Error('The transpiler did not properly export the \"transpile\" method. $gwtExport: ' + JSON.stringify(goog.global.$gwtExport));\n }\n goog.global.$jscomp.transpile = goog.global.$gwtExport.$jscomp.transpile;\n d = goog.global.$jscomp;\n e = d.transpile;\n }\n }\n e || (e = d.transpile = function(a, b) {\n goog.logToConsole_(b + \" requires transpilation but no transpiler was found.\");\n return a;\n });\n return e(a, b, c);\n};\ngoog.typeOf = function(a) {\n var b = typeof a;\n if (\"object\" == b) {\n if (a) {\n if (a instanceof Array) {\n return \"array\";\n }\n if (a instanceof Object) {\n return b;\n }\n var c = Object.prototype.toString.call(a);\n if (\"[object Window]\" == c) {\n return \"object\";\n }\n if (\"[object Array]\" == c || \"number\" == typeof a.length && \"undefined\" != typeof a.splice && \"undefined\" != typeof a.propertyIsEnumerable && !a.propertyIsEnumerable(\"splice\")) {\n return \"array\";\n }\n if (\"[object Function]\" == c || \"undefined\" != typeof a.call && \"undefined\" != typeof a.propertyIsEnumerable && !a.propertyIsEnumerable(\"call\")) {\n return \"function\";\n }\n } else {\n return \"null\";\n }\n } else {\n if (\"function\" == b && \"undefined\" == typeof a.call) {\n return \"object\";\n }\n }\n return b;\n};\ngoog.isNull = function(a) {\n return null === a;\n};\ngoog.isDefAndNotNull = function(a) {\n return null != a;\n};\ngoog.isArray = function(a) {\n return \"array\" == goog.typeOf(a);\n};\ngoog.isArrayLike = function(a) {\n var b = goog.typeOf(a);\n return \"array\" == b || \"object\" == b && \"number\" == typeof a.length;\n};\ngoog.isDateLike = function(a) {\n return goog.isObject(a) && \"function\" == typeof a.getFullYear;\n};\ngoog.isFunction = function(a) {\n return \"function\" == goog.typeOf(a);\n};\ngoog.isObject = function(a) {\n var b = typeof a;\n return \"object\" == b && null != a || \"function\" == b;\n};\ngoog.getUid = function(a) {\n return a[goog.UID_PROPERTY_] || (a[goog.UID_PROPERTY_] = ++goog.uidCounter_);\n};\ngoog.hasUid = function(a) {\n return !!a[goog.UID_PROPERTY_];\n};\ngoog.removeUid = function(a) {\n null !== a && \"removeAttribute\" in a && a.removeAttribute(goog.UID_PROPERTY_);\n try {\n delete a[goog.UID_PROPERTY_];\n } catch (b) {\n }\n};\ngoog.UID_PROPERTY_ = \"closure_uid_\" + (1e9 * Math.random() >>> 0);\ngoog.uidCounter_ = 0;\ngoog.getHashCode = goog.getUid;\ngoog.removeHashCode = goog.removeUid;\ngoog.cloneObject = function(a) {\n var b = goog.typeOf(a);\n if (\"object\" == b || \"array\" == b) {\n if (\"function\" === typeof a.clone) {\n return a.clone();\n }\n b = \"array\" == b ? [] : {};\n for (var c in a) {\n b[c] = goog.cloneObject(a[c]);\n }\n return b;\n }\n return a;\n};\ngoog.bindNative_ = function(a, b, c) {\n return a.call.apply(a.bind, arguments);\n};\ngoog.bindJs_ = function(a, b, c) {\n if (!a) {\n throw Error();\n }\n if (2 < arguments.length) {\n var d = Array.prototype.slice.call(arguments, 2);\n return function() {\n var c = Array.prototype.slice.call(arguments);\n Array.prototype.unshift.apply(c, d);\n return a.apply(b, c);\n };\n }\n return function() {\n return a.apply(b, arguments);\n };\n};\ngoog.bind = function(a, b, c) {\n Function.prototype.bind && -1 != Function.prototype.bind.toString().indexOf(\"native code\") ? goog.bind = goog.bindNative_ : goog.bind = goog.bindJs_;\n return goog.bind.apply(null, arguments);\n};\ngoog.partial = function(a, b) {\n var c = Array.prototype.slice.call(arguments, 1);\n return function() {\n var b = c.slice();\n b.push.apply(b, arguments);\n return a.apply(this, b);\n };\n};\ngoog.mixin = function(a, b) {\n for (var c in b) {\n a[c] = b[c];\n }\n};\ngoog.now = goog.TRUSTED_SITE && Date.now || function() {\n return +new Date;\n };\ngoog.globalEval = function(a) {\n if (goog.global.execScript) {\n goog.global.execScript(a, \"JavaScript\");\n } else {\n if (goog.global.eval) {\n if (null == goog.evalWorksForGlobals_) {\n try {\n goog.global.eval(\"var _evalTest_ = 1;\");\n } catch (d) {\n }\n if (\"undefined\" != typeof goog.global._evalTest_) {\n try {\n delete goog.global._evalTest_;\n } catch (d) {\n }\n goog.evalWorksForGlobals_ = !0;\n } else {\n goog.evalWorksForGlobals_ = !1;\n }\n }\n if (goog.evalWorksForGlobals_) {\n goog.global.eval(a);\n } else {\n var b = goog.global.document, c = b.createElement(\"SCRIPT\");\n c.type = \"text/javascript\";\n c.defer = !1;\n c.appendChild(b.createTextNode(a));\n b.head.appendChild(c);\n b.head.removeChild(c);\n }\n } else {\n throw Error(\"goog.globalEval not available\");\n }\n }\n};\ngoog.evalWorksForGlobals_ = null;\ngoog.getCssName = function(a, b) {\n if (\".\" == String(a).charAt(0)) {\n throw Error('className passed in goog.getCssName must not start with \".\". You passed: ' + a);\n }\n var c = function(a) {\n return goog.cssNameMapping_[a] || a;\n }, d = function(a) {\n a = a.split(\"-\");\n for (var b = [], d = 0; d < a.length; d++) {\n b.push(c(a[d]));\n }\n return b.join(\"-\");\n };\n d = goog.cssNameMapping_ ? \"BY_WHOLE\" == goog.cssNameMappingStyle_ ? c : d : function(a) {\n return a;\n };\n d = b ? a + \"-\" + d(b) : d(a);\n return goog.global.CLOSURE_CSS_NAME_MAP_FN ? goog.global.CLOSURE_CSS_NAME_MAP_FN(d) : d;\n};\ngoog.setCssNameMapping = function(a, b) {\n goog.cssNameMapping_ = a;\n goog.cssNameMappingStyle_ = b;\n};\n!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING && (goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING);\ngoog.getMsg = function(a, b) {\n b && (a = a.replace(/\\{\\$([^}]+)}/g, function(a, d) {\n return null != b && d in b ? b[d] : a;\n }));\n return a;\n};\ngoog.getMsgWithFallback = function(a, b) {\n return a;\n};\ngoog.exportSymbol = function(a, b, c) {\n goog.exportPath_(a, b, c);\n};\ngoog.exportProperty = function(a, b, c) {\n a[b] = c;\n};\ngoog.inherits = function(a, b) {\n function c() {\n }\n c.prototype = b.prototype;\n a.superClass_ = b.prototype;\n a.prototype = new c;\n a.prototype.constructor = a;\n a.base = function(a, c, f) {\n for (var d = Array(arguments.length - 2), e = 2; e < arguments.length; e++) {\n d[e - 2] = arguments[e];\n }\n return b.prototype[c].apply(a, d);\n };\n};\ngoog.base = function(a, b, c) {\n var d = arguments.callee.caller;\n if (goog.STRICT_MODE_COMPATIBLE || goog.DEBUG && !d) {\n throw Error(\"arguments.caller not defined. goog.base() cannot be used with strict mode code. See http://www.ecma-international.org/ecma-262/5.1/#sec-C\");\n }\n if (\"undefined\" !== typeof d.superClass_) {\n for (var e = Array(arguments.length - 1), f = 1; f < arguments.length; f++) {\n e[f - 1] = arguments[f];\n }\n return d.superClass_.constructor.apply(a, e);\n }\n if (\"string\" != typeof b && \"symbol\" != typeof b) {\n throw Error(\"method names provided to goog.base must be a string or a symbol\");\n }\n e = Array(arguments.length - 2);\n for (f = 2; f < arguments.length; f++) {\n e[f - 2] = arguments[f];\n }\n f = !1;\n for (var g = a.constructor; g; g = g.superClass_ && g.superClass_.constructor) {\n if (g.prototype[b] === d) {\n f = !0;\n } else {\n if (f) {\n return g.prototype[b].apply(a, e);\n }\n }\n }\n if (a[b] === d) {\n return a.constructor.prototype[b].apply(a, e);\n }\n throw Error(\"goog.base called from a method of one name to a method of a different name\");\n};\ngoog.scope = function(a) {\n if (goog.isInModuleLoader_()) {\n throw Error(\"goog.scope is not supported within a module.\");\n }\n a.call(goog.global);\n};\nCOMPILED || (goog.global.COMPILED = COMPILED);\ngoog.defineClass = function(a, b) {\n var c = b.constructor, d = b.statics;\n c && c != Object.prototype.constructor || (c = function() {\n throw Error(\"cannot instantiate an interface (no constructor defined).\");\n });\n c = goog.defineClass.createSealingConstructor_(c, a);\n a && goog.inherits(c, a);\n delete b.constructor;\n delete b.statics;\n goog.defineClass.applyProperties_(c.prototype, b);\n null != d && (d instanceof Function ? d(c) : goog.defineClass.applyProperties_(c, d));\n return c;\n};\ngoog.defineClass.SEAL_CLASS_INSTANCES = goog.DEBUG;\ngoog.defineClass.createSealingConstructor_ = function(a, b) {\n if (!goog.defineClass.SEAL_CLASS_INSTANCES) {\n return a;\n }\n var c = !goog.defineClass.isUnsealable_(b), d = function() {\n var b = a.apply(this, arguments) || this;\n b[goog.UID_PROPERTY_] = b[goog.UID_PROPERTY_];\n this.constructor === d && c && Object.seal instanceof Function && Object.seal(b);\n return b;\n };\n return d;\n};\ngoog.defineClass.isUnsealable_ = function(a) {\n return a && a.prototype && a.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_];\n};\ngoog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = \"constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf\".split(\" \");\ngoog.defineClass.applyProperties_ = function(a, b) {\n for (var c in b) {\n Object.prototype.hasOwnProperty.call(b, c) && (a[c] = b[c]);\n }\n for (var d = 0; d < goog.defineClass.OBJECT_PROTOTYPE_FIELDS_.length; d++) {\n c = goog.defineClass.OBJECT_PROTOTYPE_FIELDS_[d], Object.prototype.hasOwnProperty.call(b, c) && (a[c] = b[c]);\n }\n};\ngoog.tagUnsealableClass = function(a) {\n !COMPILED && goog.defineClass.SEAL_CLASS_INSTANCES && (a.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_] = !0);\n};\ngoog.UNSEALABLE_CONSTRUCTOR_PROPERTY_ = \"goog_defineClass_legacy_unsealable\";\n!COMPILED && goog.DEPENDENCIES_ENABLED && (goog.inHtmlDocument_ = function() {\n var a = goog.global.document;\n return null != a && \"write\" in a;\n}, goog.isDocumentLoading_ = function() {\n var a = goog.global.document;\n return a.attachEvent ? \"complete\" != a.readyState : \"loading\" == a.readyState;\n}, goog.findBasePath_ = function() {\n if (goog.isDef(goog.global.CLOSURE_BASE_PATH) && goog.isString(goog.global.CLOSURE_BASE_PATH)) {\n goog.basePath = goog.global.CLOSURE_BASE_PATH;\n } else {\n if (goog.inHtmlDocument_()) {\n var a = goog.global.document, b = a.currentScript;\n a = b ? [b] : a.getElementsByTagName(\"SCRIPT\");\n for (b = a.length - 1; 0 <= b; --b) {\n var c = a[b].src, d = c.lastIndexOf(\"?\");\n d = -1 == d ? c.length : d;\n if (\"base.js\" == c.substr(d - 7, 7)) {\n goog.basePath = c.substr(0, d - 7);\n break;\n }\n }\n }\n }\n}, goog.findBasePath_(), goog.Transpiler = function() {\n this.requiresTranspilation_ = null;\n this.transpilationTarget_ = goog.TRANSPILE_TO_LANGUAGE;\n}, goog.Transpiler.prototype.createRequiresTranspilation_ = function() {\n function a(a, b) {\n e ? d[a] = !0 : b() ? (c = a, d[a] = !1) : e = d[a] = !0;\n }\n function b(a) {\n try {\n return !!eval(a);\n } catch (h) {\n return !1;\n }\n }\n var c = \"es3\", d = {es3:!1}, e = !1, f = goog.global.navigator && goog.global.navigator.userAgent ? goog.global.navigator.userAgent : \"\";\n a(\"es5\", function() {\n return b(\"[1,].length==1\");\n });\n a(\"es6\", function() {\n return f.match(/Edge\\/(\\d+)(\\.\\d)*/i) ? !1 : b('(()=>{\"use strict\";class X{constructor(){if(new.target!=String)throw 1;this.x=42}}let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof String))throw 1;for(const a of[2,3]){if(a==2)continue;function f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()==3}})()');\n });\n a(\"es6-impl\", function() {\n return !0;\n });\n a(\"es7\", function() {\n return b(\"2 ** 2 == 4\");\n });\n a(\"es8\", function() {\n return b(\"async () => 1, true\");\n });\n a(\"es9\", function() {\n return b(\"({...rest} = {}), true\");\n });\n a(\"es_next\", function() {\n return !1;\n });\n return {target:c, map:d};\n}, goog.Transpiler.prototype.needsTranspile = function(a, b) {\n if (\"always\" == goog.TRANSPILE) {\n return !0;\n }\n if (\"never\" == goog.TRANSPILE) {\n return !1;\n }\n if (!this.requiresTranspilation_) {\n var c = this.createRequiresTranspilation_();\n this.requiresTranspilation_ = c.map;\n this.transpilationTarget_ = this.transpilationTarget_ || c.target;\n }\n if (a in this.requiresTranspilation_) {\n return this.requiresTranspilation_[a] ? !0 : !goog.inHtmlDocument_() || \"es6\" != b || \"noModule\" in goog.global.document.createElement(\"script\") ? !1 : !0;\n }\n throw Error(\"Unknown language mode: \" + a);\n}, goog.Transpiler.prototype.transpile = function(a, b) {\n return goog.transpile_(a, b, this.transpilationTarget_);\n}, goog.transpiler_ = new goog.Transpiler, goog.protectScriptTag_ = function(a) {\n return a.replace(/<\\/(SCRIPT)/ig, \"\\\\x3c/$1\");\n}, goog.DebugLoader_ = function() {\n this.dependencies_ = {};\n this.idToPath_ = {};\n this.written_ = {};\n this.loadingDeps_ = [];\n this.depsToLoad_ = [];\n this.paused_ = !1;\n this.factory_ = new goog.DependencyFactory(goog.transpiler_);\n this.deferredCallbacks_ = {};\n this.deferredQueue_ = [];\n}, goog.DebugLoader_.prototype.bootstrap = function(a, b) {\n function c() {\n d && (goog.global.setTimeout(d, 0), d = null);\n }\n var d = b;\n if (a.length) {\n for (var e = [], f = 0; f < a.length; f++) {\n var g = this.getPathFromDeps_(a[f]);\n if (!g) {\n throw Error(\"Unregonized namespace: \" + a[f]);\n }\n e.push(this.dependencies_[g]);\n }\n g = goog.require;\n var h = 0;\n for (f = 0; f < a.length; f++) {\n g(a[f]), e[f].onLoad(function() {\n ++h == a.length && c();\n });\n }\n } else {\n c();\n }\n}, goog.DebugLoader_.prototype.loadClosureDeps = function() {\n this.depsToLoad_.push(this.factory_.createDependency(goog.normalizePath_(goog.basePath + \"deps.js\"), \"deps.js\", [], [], {}, !1));\n this.loadDeps_();\n}, goog.DebugLoader_.prototype.requested = function(a, b) {\n var c = this.getPathFromDeps_(a);\n if (c && (b || this.areDepsLoaded_(this.dependencies_[c].requires))) {\n var d = this.deferredCallbacks_[c];\n d && (delete this.deferredCallbacks_[c], d());\n }\n}, goog.DebugLoader_.prototype.setDependencyFactory = function(a) {\n this.factory_ = a;\n}, goog.DebugLoader_.prototype.load_ = function(a) {\n if (this.getPathFromDeps_(a)) {\n var b = this, c = [], d = function(a) {\n var e = b.getPathFromDeps_(a);\n if (!e) {\n throw Error(\"Bad dependency path or symbol: \" + a);\n }\n if (!b.written_[e]) {\n b.written_[e] = !0;\n a = b.dependencies_[e];\n for (e = 0; e < a.requires.length; e++) {\n goog.isProvided_(a.requires[e]) || d(a.requires[e]);\n }\n c.push(a);\n }\n };\n d(a);\n a = !!this.depsToLoad_.length;\n this.depsToLoad_ = this.depsToLoad_.concat(c);\n this.paused_ || a || this.loadDeps_();\n } else {\n throw a = \"goog.require could not find: \" + a, goog.logToConsole_(a), Error(a);\n }\n}, goog.DebugLoader_.prototype.loadDeps_ = function() {\n for (var a = this, b = this.paused_; this.depsToLoad_.length && !b;) {\n (function() {\n var c = !1, d = a.depsToLoad_.shift(), e = !1;\n a.loading_(d);\n var f = {pause:function() {\n if (c) {\n throw Error(\"Cannot call pause after the call to load.\");\n }\n b = !0;\n }, resume:function() {\n c ? a.resume_() : b = !1;\n }, loaded:function() {\n if (e) {\n throw Error(\"Double call to loaded.\");\n }\n e = !0;\n a.loaded_(d);\n }, pending:function() {\n for (var b = [], c = 0; c < a.loadingDeps_.length; c++) {\n b.push(a.loadingDeps_[c]);\n }\n return b;\n }, setModuleState:function(a) {\n goog.moduleLoaderState_ = {type:a, moduleName:\"\", declareLegacyNamespace:!1};\n }, registerEs6ModuleExports:function(a, b, c) {\n c && (goog.loadedModules_[c] = {exports:b, type:goog.ModuleType.ES6, moduleId:c || \"\"});\n }, registerGoogModuleExports:function(a, b) {\n goog.loadedModules_[a] = {exports:b, type:goog.ModuleType.GOOG, moduleId:a};\n }, clearModuleState:function() {\n goog.moduleLoaderState_ = null;\n }, defer:function(b) {\n if (c) {\n throw Error(\"Cannot register with defer after the call to load.\");\n }\n a.defer_(d, b);\n }, areDepsLoaded:function() {\n return a.areDepsLoaded_(d.requires);\n }};\n try {\n d.load(f);\n } finally {\n c = !0;\n }\n })();\n }\n b && this.pause_();\n}, goog.DebugLoader_.prototype.pause_ = function() {\n this.paused_ = !0;\n}, goog.DebugLoader_.prototype.resume_ = function() {\n this.paused_ && (this.paused_ = !1, this.loadDeps_());\n}, goog.DebugLoader_.prototype.loading_ = function(a) {\n this.loadingDeps_.push(a);\n}, goog.DebugLoader_.prototype.loaded_ = function(a) {\n for (var b = 0; b < this.loadingDeps_.length; b++) {\n if (this.loadingDeps_[b] == a) {\n this.loadingDeps_.splice(b, 1);\n break;\n }\n }\n for (b = 0; b < this.deferredQueue_.length; b++) {\n if (this.deferredQueue_[b] == a.path) {\n this.deferredQueue_.splice(b, 1);\n break;\n }\n }\n if (this.loadingDeps_.length == this.deferredQueue_.length && !this.depsToLoad_.length) {\n for (; this.deferredQueue_.length;) {\n this.requested(this.deferredQueue_.shift(), !0);\n }\n }\n a.loaded();\n}, goog.DebugLoader_.prototype.areDepsLoaded_ = function(a) {\n for (var b = 0; b < a.length; b++) {\n var c = this.getPathFromDeps_(a[b]);\n if (!c || !(c in this.deferredCallbacks_ || goog.isProvided_(a[b]))) {\n return !1;\n }\n }\n return !0;\n}, goog.DebugLoader_.prototype.getPathFromDeps_ = function(a) {\n return a in this.idToPath_ ? this.idToPath_[a] : a in this.dependencies_ ? a : null;\n}, goog.DebugLoader_.prototype.defer_ = function(a, b) {\n this.deferredCallbacks_[a.path] = b;\n this.deferredQueue_.push(a.path);\n}, goog.LoadController = function() {\n}, goog.LoadController.prototype.pause = function() {\n}, goog.LoadController.prototype.resume = function() {\n}, goog.LoadController.prototype.loaded = function() {\n}, goog.LoadController.prototype.pending = function() {\n}, goog.LoadController.prototype.registerEs6ModuleExports = function(a, b, c) {\n}, goog.LoadController.prototype.setModuleState = function(a) {\n}, goog.LoadController.prototype.clearModuleState = function() {\n}, goog.LoadController.prototype.defer = function(a) {\n}, goog.LoadController.prototype.areDepsLoaded = function() {\n}, goog.Dependency = function(a, b, c, d, e) {\n this.path = a;\n this.relativePath = b;\n this.provides = c;\n this.requires = d;\n this.loadFlags = e;\n this.loaded_ = !1;\n this.loadCallbacks_ = [];\n}, goog.Dependency.prototype.getPathName = function() {\n var a = this.path, b = a.indexOf(\"://\");\n 0 <= b && (a = a.substring(b + 3), b = a.indexOf(\"/\"), 0 <= b && (a = a.substring(b + 1)));\n return a;\n}, goog.Dependency.prototype.onLoad = function(a) {\n this.loaded_ ? a() : this.loadCallbacks_.push(a);\n}, goog.Dependency.prototype.loaded = function() {\n this.loaded_ = !0;\n var a = this.loadCallbacks_;\n this.loadCallbacks_ = [];\n for (var b = 0; b < a.length; b++) {\n a[b]();\n }\n}, goog.Dependency.defer_ = !1, goog.Dependency.callbackMap_ = {}, goog.Dependency.registerCallback_ = function(a) {\n var b = Math.random().toString(32);\n goog.Dependency.callbackMap_[b] = a;\n return b;\n}, goog.Dependency.unregisterCallback_ = function(a) {\n delete goog.Dependency.callbackMap_[a];\n}, goog.Dependency.callback_ = function(a, b) {\n if (a in goog.Dependency.callbackMap_) {\n for (var c = goog.Dependency.callbackMap_[a], d = [], e = 1; e < arguments.length; e++) {\n d.push(arguments[e]);\n }\n c.apply(void 0, d);\n } else {\n throw Error(\"Callback key \" + a + \" does not exist (was base.js loaded more than once?).\");\n }\n}, goog.Dependency.prototype.load = function(a) {\n if (goog.global.CLOSURE_IMPORT_SCRIPT) {\n goog.global.CLOSURE_IMPORT_SCRIPT(this.path) ? a.loaded() : a.pause();\n } else {\n if (goog.inHtmlDocument_()) {\n var b = goog.global.document;\n if (\"complete\" == b.readyState && !goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING) {\n if (/\\bdeps.js$/.test(this.path)) {\n a.loaded();\n return;\n }\n throw Error('Cannot write \"' + this.path + '\" after document load');\n }\n if (!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING && goog.isDocumentLoading_()) {\n var c = goog.Dependency.registerCallback_(function(b) {\n goog.DebugLoader_.IS_OLD_IE_ && \"complete\" != b.readyState || (goog.Dependency.unregisterCallback_(c), a.loaded());\n }), d = !goog.DebugLoader_.IS_OLD_IE_ && goog.getScriptNonce() ? ' nonce=\"' + goog.getScriptNonce() + '\"' : \"\";\n b.write('