From 8e5bcf5bdeda4b67c286bdaa27e8c4a13f5b6fff Mon Sep 17 00:00:00 2001 From: Pawel Kozlowski Date: Sun, 8 Sep 2013 19:08:50 +0200 Subject: [PATCH] v0.6.0 --- bower.json | 2 +- ui-bootstrap-tpls.js | 1295 ++++++++++++++++++++------------------ ui-bootstrap-tpls.min.js | 4 +- ui-bootstrap.js | 1265 ++++++++++++++++++++----------------- ui-bootstrap.min.js | 4 +- 5 files changed, 1373 insertions(+), 1197 deletions(-) diff --git a/bower.json b/bower.json index 87934e5..12bf8ae 100644 --- a/bower.json +++ b/bower.json @@ -3,7 +3,7 @@ "name": "https://github.com/angular-ui/bootstrap/graphs/contributors" }, "name": "angular-bootstrap", - "version": "0.5.0", + "version": "0.6.0", "main": ["./ui-bootstrap-tpls.js"], "dependencies": { "angular": ">=1" diff --git a/ui-bootstrap-tpls.js b/ui-bootstrap-tpls.js index 1aa9dd4..ed018f8 100644 --- a/ui-bootstrap-tpls.js +++ b/ui-bootstrap-tpls.js @@ -1,5 +1,5 @@ -angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dialog","ui.bootstrap.dropdownToggle","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"]); -angular.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/popup.html","template/dialog/message.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset-titles.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]); +angular.module("ui.bootstrap", ["ui.bootstrap.tpls", "ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdownToggle","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"]); +angular.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/popup.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset-titles.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]); angular.module('ui.bootstrap.transition', []) /** @@ -337,6 +337,16 @@ angular.module("ui.bootstrap.alert", []).directive('alert', function () { }; }); +angular.module('ui.bootstrap.bindHtml', []) + + .directive('bindHtmlUnsafe', function () { + return function (scope, element, attr) { + element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe); + scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { + element.html(value || ''); + }); + }; + }); angular.module('ui.bootstrap.buttons', []) .constant('buttonConfig', { @@ -408,7 +418,7 @@ angular.module('ui.bootstrap.buttons', []) /** * @ngdoc overview * @name ui.bootstrap.carousel -* +* * @description * AngularJS version of an image carousel. * @@ -439,10 +449,10 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition']) } function goNext() { //If we have a slide to transition from and we have a transition type and we're allowed, go - if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) { + if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) { //We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime nextSlide.$element.addClass(direction); - nextSlide.$element[0].offsetWidth = nextSlide.$element[0].offsetWidth; //force reflow + var reflow = nextSlide.$element[0].offsetWidth; //force reflow //Set all other slides to stop doing their stuff for the new transition angular.forEach(slides, function(slide) { @@ -481,7 +491,7 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition']) $scope.next = function() { var newIndex = (currentIndex + 1) % slides.length; - + //Prevent this user-triggered transition from occurring if there is already one in progress if (!$scope.$currentTransition) { return self.select(slides[newIndex], 'next'); @@ -490,7 +500,7 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition']) $scope.prev = function() { var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1; - + //Prevent this user-triggered transition from occurring if there is already one in progress if (!$scope.$currentTransition) { return self.select(slides[newIndex], 'prev'); @@ -707,7 +717,7 @@ function CarouselDemoCtrl($scope) { var lastValue = scope.active = getActive(scope.$parent); scope.$watch(function parentActiveWatch() { var parentActive = getActive(scope.$parent); - + if (parentActive !== scope.active) { // we are out of sync and need to copy if (parentActive !== lastValue) { @@ -747,13 +757,6 @@ angular.module('ui.bootstrap.position', []) */ .factory('$position', ['$document', '$window', function ($document, $window) { - var mouseX, mouseY; - - $document.bind('mousemove', function mouseMoved(event) { - mouseX = event.pageX; - mouseY = event.pageY; - }); - function getStyle(el, cssprop) { if (el.currentStyle) { //IE return el.currentStyle[cssprop]; @@ -817,16 +820,9 @@ angular.module('ui.bootstrap.position', []) return { width: element.prop('offsetWidth'), height: element.prop('offsetHeight'), - top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop), - left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft) + top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop), + left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft) }; - }, - - /** - * Provides the coordinates of the mouse - */ - mouse: function () { - return {x: mouseX, y: mouseY}; } }; }]); @@ -1105,26 +1101,9 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon scope.$destroy(); }); - function formatDate(value) { - return (value) ? dateFilter(value, dateFormat) : null; - } - ngModel.$formatters.push(formatDate); - - // TODO: reverse from dateFilter string to Date object - function parseDate(value) { - if ( value ) { - var date = new Date(value); - if (!isNaN(date)) { - return date; - } - } - return value; - } - ngModel.$parsers.push(parseDate); - var getIsOpen, setIsOpen; - if ( attrs.open ) { - getIsOpen = $parse(attrs.open); + if ( attrs.isOpen ) { + getIsOpen = $parse(attrs.isOpen); setIsOpen = getIsOpen.assign; originalScope.$watch(getIsOpen, function updateOpen(value) { @@ -1166,33 +1145,58 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon datepickerEl.attr(angular.extend({}, originalScope.$eval(attrs.datepickerOptions))); } - var $setModelValue = $parse(attrs.ngModel).assign; + // TODO: reverse from dateFilter string to Date object + function parseDate(viewValue) { + if (!viewValue) { + ngModel.$setValidity('date', true); + return null; + } else if (angular.isDate(viewValue)) { + ngModel.$setValidity('date', true); + return viewValue; + } else if (angular.isString(viewValue)) { + var date = new Date(viewValue); + if (isNaN(date)) { + ngModel.$setValidity('date', false); + return undefined; + } else { + ngModel.$setValidity('date', true); + return date; + } + } else { + ngModel.$setValidity('date', false); + return undefined; + } + } + ngModel.$parsers.unshift(parseDate); // Inner change scope.dateSelection = function() { - $setModelValue(originalScope, scope.date); + ngModel.$setViewValue(scope.date); + ngModel.$render(); + if (closeOnDateSelection) { setOpen( false ); } }; + element.bind('input change keyup', function() { + scope.$apply(function() { + updateCalendar(); + }); + }); + // Outter change - scope.$watch(function() { - return ngModel.$modelValue; - }, function(value) { - if (angular.isString(value)) { - var date = parseDate(value); - - if (value && !date) { - $setModelValue(originalScope, null); - throw new Error(value + ' cannot be parsed to a date object.'); - } else { - value = date; - } - } - scope.date = value; + ngModel.$render = function() { + var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : ''; + element.val(date); + + updateCalendar(); + }; + + function updateCalendar() { + scope.date = ngModel.$modelValue; updatePosition(); - }); + } function addWatchableAttribute(attribute, scopeProperty, datepickerAttribute) { if (attribute) { @@ -1219,15 +1223,22 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon scope.position.top = scope.position.top + element.prop('offsetHeight'); } + var documentBindingInitialized = false, elementFocusInitialized = false; scope.$watch('isOpen', function(value) { if (value) { updatePosition(); $document.bind('click', documentClickBind); - element.unbind('focus', elementFocusBind); - element.focus(); + if(elementFocusInitialized) { + element.unbind('focus', elementFocusBind); + } + element[0].focus(); + documentBindingInitialized = true; } else { - $document.unbind('click', documentClickBind); + if(documentBindingInitialized) { + $document.unbind('click', documentClickBind); + } element.bind('focus', elementFocusBind); + elementFocusInitialized = true; } if ( setIsOpen ) { @@ -1235,6 +1246,8 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon } }); + var $setModelValue = $parse(attrs.ngModel).assign; + scope.today = function() { $setModelValue(originalScope, new Date()); }; @@ -1261,286 +1274,6 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon } }; }]); -// The `$dialogProvider` can be used to configure global defaults for your -// `$dialog` service. -var dialogModule = angular.module('ui.bootstrap.dialog', ['ui.bootstrap.transition']); - -dialogModule.controller('MessageBoxController', ['$scope', 'dialog', 'model', function($scope, dialog, model){ - $scope.title = model.title; - $scope.message = model.message; - $scope.buttons = model.buttons; - $scope.close = function(res){ - dialog.close(res); - }; -}]); - -dialogModule.provider("$dialog", function(){ - - // The default options for all dialogs. - var defaults = { - backdrop: true, - dialogClass: 'modal', - backdropClass: 'modal-backdrop', - transitionClass: 'fade', - triggerClass: 'in', - resolve:{}, - backdropFade: false, - dialogFade:false, - keyboard: true, // close with esc key - backdropClick: true // only in conjunction with backdrop=true - /* other options: template, templateUrl, controller */ - }; - - var globalOptions = {}; - - var activeBackdrops = {value : 0}; - - // The `options({})` allows global configuration of all dialogs in the application. - // - // var app = angular.module('App', ['ui.bootstrap.dialog'], function($dialogProvider){ - // // don't close dialog when backdrop is clicked by default - // $dialogProvider.options({backdropClick: false}); - // }); - this.options = function(value){ - globalOptions = value; - }; - - // Returns the actual `$dialog` service that is injected in controllers - this.$get = ["$http", "$document", "$compile", "$rootScope", "$controller", "$templateCache", "$q", "$transition", "$injector", - function ($http, $document, $compile, $rootScope, $controller, $templateCache, $q, $transition, $injector) { - - var body = $document.find('body'); - - function createElement(clazz) { - var el = angular.element("
"); - el.addClass(clazz); - return el; - } - - // The `Dialog` class represents a modal dialog. The dialog class can be invoked by providing an options object - // containing at lest template or templateUrl and controller: - // - // var d = new Dialog({templateUrl: 'foo.html', controller: 'BarController'}); - // - // Dialogs can also be created using templateUrl and controller as distinct arguments: - // - // var d = new Dialog('path/to/dialog.html', MyDialogController); - function Dialog(opts) { - - var self = this, options = this.options = angular.extend({}, defaults, globalOptions, opts); - this._open = false; - - this.backdropEl = createElement(options.backdropClass); - if(options.backdropFade){ - this.backdropEl.addClass(options.transitionClass); - this.backdropEl.removeClass(options.triggerClass); - } - - this.modalEl = createElement(options.dialogClass); - if(options.dialogFade){ - this.modalEl.addClass(options.transitionClass); - this.modalEl.removeClass(options.triggerClass); - } - - this.handledEscapeKey = function(e) { - if (e.which === 27) { - self.close(); - e.preventDefault(); - self.$scope.$apply(); - } - }; - - this.handleBackDropClick = function(e) { - self.close(); - e.preventDefault(); - self.$scope.$apply(); - }; - } - - // The `isOpen()` method returns wether the dialog is currently visible. - Dialog.prototype.isOpen = function(){ - return this._open; - }; - - // The `open(templateUrl, controller)` method opens the dialog. - // Use the `templateUrl` and `controller` arguments if specifying them at dialog creation time is not desired. - Dialog.prototype.open = function(templateUrl, controller){ - var self = this, options = this.options; - - if(templateUrl){ - options.templateUrl = templateUrl; - } - if(controller){ - options.controller = controller; - } - - if(!(options.template || options.templateUrl)) { - throw new Error('Dialog.open expected template or templateUrl, neither found. Use options or open method to specify them.'); - } - - this._loadResolves().then(function(locals) { - var $scope = locals.$scope = self.$scope = locals.$scope ? locals.$scope : $rootScope.$new(); - - self.modalEl.html(locals.$template); - - if (self.options.controller) { - var ctrl = $controller(self.options.controller, locals); - self.modalEl.children().data('ngControllerController', ctrl); - } - - $compile(self.modalEl)($scope); - self._addElementsToDom(); - - // trigger tranisitions - setTimeout(function(){ - if(self.options.dialogFade){ self.modalEl.addClass(self.options.triggerClass); } - if(self.options.backdropFade){ self.backdropEl.addClass(self.options.triggerClass); } - }); - - self._bindEvents(); - }); - - this.deferred = $q.defer(); - return this.deferred.promise; - }; - - // closes the dialog and resolves the promise returned by the `open` method with the specified result. - Dialog.prototype.close = function(result){ - var self = this; - var fadingElements = this._getFadingElements(); - - if(fadingElements.length > 0){ - for (var i = fadingElements.length - 1; i >= 0; i--) { - $transition(fadingElements[i], removeTriggerClass).then(onCloseComplete); - } - return; - } - - this._onCloseComplete(result); - - function removeTriggerClass(el){ - el.removeClass(self.options.triggerClass); - } - - function onCloseComplete(){ - if(self._open){ - self._onCloseComplete(result); - } - } - }; - - Dialog.prototype._getFadingElements = function(){ - var elements = []; - if(this.options.dialogFade){ - elements.push(this.modalEl); - } - if(this.options.backdropFade){ - elements.push(this.backdropEl); - } - - return elements; - }; - - Dialog.prototype._bindEvents = function() { - if(this.options.keyboard){ body.bind('keydown', this.handledEscapeKey); } - if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.bind('click', this.handleBackDropClick); } - }; - - Dialog.prototype._unbindEvents = function() { - if(this.options.keyboard){ body.unbind('keydown', this.handledEscapeKey); } - if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.unbind('click', this.handleBackDropClick); } - }; - - Dialog.prototype._onCloseComplete = function(result) { - this._removeElementsFromDom(); - this._unbindEvents(); - - this.deferred.resolve(result); - }; - - Dialog.prototype._addElementsToDom = function(){ - body.append(this.modalEl); - - if(this.options.backdrop) { - if (activeBackdrops.value === 0) { - body.append(this.backdropEl); - } - activeBackdrops.value++; - } - - this._open = true; - }; - - Dialog.prototype._removeElementsFromDom = function(){ - this.modalEl.remove(); - - if(this.options.backdrop) { - activeBackdrops.value--; - if (activeBackdrops.value === 0) { - this.backdropEl.remove(); - } - } - this._open = false; - }; - - // Loads all `options.resolve` members to be used as locals for the controller associated with the dialog. - Dialog.prototype._loadResolves = function(){ - var values = [], keys = [], templatePromise, self = this; - - if (this.options.template) { - templatePromise = $q.when(this.options.template); - } else if (this.options.templateUrl) { - templatePromise = $http.get(this.options.templateUrl, {cache:$templateCache}) - .then(function(response) { return response.data; }); - } - - angular.forEach(this.options.resolve || [], function(value, key) { - keys.push(key); - values.push(angular.isString(value) ? $injector.get(value) : $injector.invoke(value)); - }); - - keys.push('$template'); - values.push(templatePromise); - - return $q.all(values).then(function(values) { - var locals = {}; - angular.forEach(values, function(value, index) { - locals[keys[index]] = value; - }); - locals.dialog = self; - return locals; - }); - }; - - // The actual `$dialog` service that is injected in controllers. - return { - // Creates a new `Dialog` with the specified options. - dialog: function(opts){ - return new Dialog(opts); - }, - // creates a new `Dialog` tied to the default message box template and controller. - // - // Arguments `title` and `message` are rendered in the modal header and body sections respectively. - // The `buttons` array holds an object with the following members for each button to include in the - // modal footer section: - // - // * `result`: the result to pass to the `close` method of the dialog when the button is clicked - // * `label`: the label of the button - // * `cssClass`: additional css class(es) to apply to the button for styling - messageBox: function(title, message, buttons){ - return new Dialog({templateUrl: 'template/dialog/message.html', controller: 'MessageBoxController', resolve: - {model: function() { - return { - title: title, - message: message, - buttons: buttons - }; - } - }}); - } - }; - }]; -}); /* * dropdownToggle - Provides dropdown menu functionality in place of bootstrap js @@ -1594,93 +1327,391 @@ angular.module('ui.bootstrap.dropdownToggle', []).directive('dropdownToggle', [' } }; }]); -angular.module('ui.bootstrap.modal', ['ui.bootstrap.dialog']) -.directive('modal', ['$parse', '$dialog', function($parse, $dialog) { - return { - restrict: 'EA', - terminal: true, - link: function(scope, elm, attrs) { - var opts = angular.extend({}, scope.$eval(attrs.uiOptions || attrs.bsOptions || attrs.options)); - var shownExpr = attrs.modal || attrs.show; - var setClosed; - - // Create a dialog with the template as the contents of the directive - // Add the current scope as the resolve in order to make the directive scope as a dialog controller scope - opts = angular.extend(opts, { - template: elm.html(), - resolve: { $scope: function() { return scope; } } - }); - var dialog = $dialog.dialog(opts); +angular.module('ui.bootstrap.modal', []) - elm.remove(); +/** + * A helper, internal data structure that acts as a map but also allows getting / removing + * elements in the LIFO order + */ + .factory('$$stackedMap', function () { + return { + createNew: function () { + var stack = []; - if (attrs.close) { - setClosed = function() { - $parse(attrs.close)(scope); + return { + add: function (key, value) { + stack.push({ + key: key, + value: value + }); + }, + get: function (key) { + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + return stack[i]; + } + } + }, + keys: function() { + var keys = []; + for (var i = 0; i < stack.length; i++) { + keys.push(stack[i].key); + } + return keys; + }, + top: function () { + return stack[stack.length - 1]; + }, + remove: function (key) { + var idx = -1; + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + idx = i; + break; + } + } + return stack.splice(idx, 1)[0]; + }, + removeTop: function () { + return stack.splice(stack.length - 1, 1)[0]; + }, + length: function () { + return stack.length; + } }; - } else { - setClosed = function() { - if (angular.isFunction($parse(shownExpr).assign)) { - $parse(shownExpr).assign(scope, false); + } + }; + }) + +/** + * A helper directive for the $modal service. It creates a backdrop element. + */ + .directive('modalBackdrop', ['$modalStack', '$timeout', function ($modalStack, $timeout) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/modal/backdrop.html', + link: function (scope, element, attrs) { + + //trigger CSS transitions + $timeout(function () { + scope.animate = true; + }); + + scope.close = function (evt) { + var modal = $modalStack.getTop(); + if (modal && modal.value.backdrop && modal.value.backdrop != 'static') { + evt.preventDefault(); + evt.stopPropagation(); + $modalStack.dismiss(modal.key, 'backdrop click'); } }; } + }; + }]) - scope.$watch(shownExpr, function(isShown, oldShown) { - if (isShown) { - dialog.open().then(function(){ - setClosed(); - }); - } else { - //Make sure it is not opened - if (dialog.isOpen()){ - dialog.close(); + .directive('modalWindow', ['$timeout', function ($timeout) { + return { + restrict: 'EA', + scope: { + index: '@' + }, + replace: true, + transclude: true, + templateUrl: 'template/modal/window.html', + link: function (scope, element, attrs) { + scope.windowClass = attrs.windowClass || ''; + + //trigger CSS transitions + $timeout(function () { + scope.animate = true; + }); + } + }; + }]) + + .factory('$modalStack', ['$document', '$compile', '$rootScope', '$$stackedMap', + function ($document, $compile, $rootScope, $$stackedMap) { + + var backdropjqLiteEl, backdropDomEl; + var backdropScope = $rootScope.$new(true); + var body = $document.find('body').eq(0); + var openedWindows = $$stackedMap.createNew(); + var $modalStack = {}; + + function backdropIndex() { + var topBackdropIndex = -1; + var opened = openedWindows.keys(); + for (var i = 0; i < opened.length; i++) { + if (openedWindows.get(opened[i]).value.backdrop) { + topBackdropIndex = i; } } + return topBackdropIndex; + } + + $rootScope.$watch(backdropIndex, function(newBackdropIndex){ + backdropScope.index = newBackdropIndex; }); - } - }; -}]); + + function removeModalWindow(modalInstance) { + + var modalWindow = openedWindows.get(modalInstance).value; + + //clean up the stack + openedWindows.remove(modalInstance); + + //remove window DOM element + modalWindow.modalDomEl.remove(); + + //remove backdrop if no longer needed + if (backdropIndex() == -1) { + backdropDomEl.remove(); + backdropDomEl = undefined; + } + + //destroy scope + modalWindow.modalScope.$destroy(); + } + + $document.bind('keydown', function (evt) { + var modal; + + if (evt.which === 27) { + modal = openedWindows.top(); + if (modal && modal.value.keyboard) { + $rootScope.$apply(function () { + $modalStack.dismiss(modal.key); + }); + } + } + }); + + $modalStack.open = function (modalInstance, modal) { + + openedWindows.add(modalInstance, { + deferred: modal.deferred, + modalScope: modal.scope, + backdrop: modal.backdrop, + keyboard: modal.keyboard + }); + + var angularDomEl = angular.element('
'); + angularDomEl.attr('window-class', modal.windowClass); + angularDomEl.attr('index', openedWindows.length() - 1); + angularDomEl.html(modal.content); + + var modalDomEl = $compile(angularDomEl)(modal.scope); + openedWindows.top().value.modalDomEl = modalDomEl; + body.append(modalDomEl); + + if (backdropIndex() >= 0 && !backdropDomEl) { + backdropjqLiteEl = angular.element('
'); + backdropDomEl = $compile(backdropjqLiteEl)(backdropScope); + body.append(backdropDomEl); + } + }; + + $modalStack.close = function (modalInstance, result) { + var modal = openedWindows.get(modalInstance); + if (modal) { + modal.value.deferred.resolve(result); + removeModalWindow(modalInstance); + } + }; + + $modalStack.dismiss = function (modalInstance, reason) { + var modalWindow = openedWindows.get(modalInstance).value; + if (modalWindow) { + modalWindow.deferred.reject(reason); + removeModalWindow(modalInstance); + } + }; + + $modalStack.getTop = function () { + return openedWindows.top(); + }; + + return $modalStack; + }]) + + .provider('$modal', function () { + + var $modalProvider = { + options: { + backdrop: true, //can be also false or 'static' + keyboard: true + }, + $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack', + function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) { + + var $modal = {}; + + function getTemplatePromise(options) { + return options.template ? $q.when(options.template) : + $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) { + return result.data; + }); + } + + function getResolvePromises(resolves) { + var promisesArr = []; + angular.forEach(resolves, function (value, key) { + if (angular.isFunction(value) || angular.isArray(value)) { + promisesArr.push($q.when($injector.invoke(value))); + } + }); + return promisesArr; + } + + $modal.open = function (modalOptions) { + + var modalResultDeferred = $q.defer(); + var modalOpenedDeferred = $q.defer(); + + //prepare an instance of a modal to be injected into controllers and returned to a caller + var modalInstance = { + result: modalResultDeferred.promise, + opened: modalOpenedDeferred.promise, + close: function (result) { + $modalStack.close(modalInstance, result); + }, + dismiss: function (reason) { + $modalStack.dismiss(modalInstance, reason); + } + }; + + //merge and clean up options + modalOptions = angular.extend({}, $modalProvider.options, modalOptions); + modalOptions.resolve = modalOptions.resolve || {}; + + //verify options + if (!modalOptions.template && !modalOptions.templateUrl) { + throw new Error('One of template or templateUrl options is required.'); + } + + var templateAndResolvePromise = + $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve))); + + + templateAndResolvePromise.then(function resolveSuccess(tplAndVars) { + + var modalScope = (modalOptions.scope || $rootScope).$new(); + modalScope.$close = modalInstance.close; + modalScope.$dismiss = modalInstance.dismiss; + + var ctrlInstance, ctrlLocals = {}; + var resolveIter = 1; + + //controllers + if (modalOptions.controller) { + ctrlLocals.$scope = modalScope; + ctrlLocals.$modalInstance = modalInstance; + angular.forEach(modalOptions.resolve, function (value, key) { + ctrlLocals[key] = tplAndVars[resolveIter++]; + }); + + ctrlInstance = $controller(modalOptions.controller, ctrlLocals); + } + + $modalStack.open(modalInstance, { + scope: modalScope, + deferred: modalResultDeferred, + content: tplAndVars[0], + backdrop: modalOptions.backdrop, + keyboard: modalOptions.keyboard, + windowClass: modalOptions.windowClass + }); + + }, function resolveError(reason) { + modalResultDeferred.reject(reason); + }); + + templateAndResolvePromise.then(function () { + modalOpenedDeferred.resolve(true); + }, function () { + modalOpenedDeferred.reject(false); + }); + + return modalInstance; + }; + + return $modal; + }] + }; + + return $modalProvider; + }); angular.module('ui.bootstrap.pagination', []) -.controller('PaginationController', ['$scope', '$interpolate', function ($scope, $interpolate) { +.controller('PaginationController', ['$scope', '$attrs', '$parse', '$interpolate', function ($scope, $attrs, $parse, $interpolate) { + var self = this; - this.currentPage = 1; + this.init = function(defaultItemsPerPage) { + if ($attrs.itemsPerPage) { + $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { + self.itemsPerPage = parseInt(value, 10); + $scope.totalPages = self.calculateTotalPages(); + }); + } else { + this.itemsPerPage = defaultItemsPerPage; + } + }; this.noPrevious = function() { - return this.currentPage === 1; + return this.page === 1; }; this.noNext = function() { - return this.currentPage === $scope.numPages; + return this.page === $scope.totalPages; }; this.isActive = function(page) { - return this.currentPage === page; + return this.page === page; }; - this.reset = function() { - $scope.pages = []; - this.currentPage = parseInt($scope.currentPage, 10); + this.calculateTotalPages = function() { + return this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); + }; - if ( this.currentPage > $scope.numPages ) { - $scope.selectPage($scope.numPages); - } + this.getAttributeValue = function(attribute, defaultValue, interpolate) { + return angular.isDefined(attribute) ? (interpolate ? $interpolate(attribute)($scope.$parent) : $scope.$parent.$eval(attribute)) : defaultValue; + }; + + this.render = function() { + this.page = parseInt($scope.page, 10) || 1; + $scope.pages = this.getPages(this.page, $scope.totalPages); }; - var self = this; $scope.selectPage = function(page) { - if ( ! self.isActive(page) && page > 0 && page <= $scope.numPages) { - $scope.currentPage = page; + if ( ! self.isActive(page) && page > 0 && page <= $scope.totalPages) { + $scope.page = page; $scope.onSelectPage({ page: page }); } }; - this.getAttributeValue = function(attribute, defaultValue, interpolate) { - return angular.isDefined(attribute) ? (interpolate ? $interpolate(attribute)($scope.$parent) : $scope.$parent.$eval(attribute)) : defaultValue; - }; + $scope.$watch('totalItems', function() { + $scope.totalPages = self.calculateTotalPages(); + }); + + $scope.$watch('totalPages', function(value) { + if ( $attrs.numPages ) { + $scope.numPages = value; // Readonly variable + } + + if ( self.page > value ) { + $scope.selectPage(value); + } else { + self.render(); + } + }); + + $scope.$watch('page', function() { + self.render(); + }); }]) .constant('paginationConfig', { + itemsPerPage: 10, boundaryLinks: false, directionLinks: true, firstText: 'First', @@ -1690,14 +1721,14 @@ angular.module('ui.bootstrap.pagination', []) rotate: true }) -.directive('pagination', ['paginationConfig', function(config) { +.directive('pagination', ['$parse', 'paginationConfig', function($parse, config) { return { restrict: 'EA', scope: { - numPages: '=', - currentPage: '=', - maxSize: '=', - onSelectPage: '&' + page: '=', + totalItems: '=', + onSelectPage:' &', + numPages: '=' }, controller: 'PaginationController', templateUrl: 'template/pagination/pagination.html', @@ -1705,13 +1736,23 @@ angular.module('ui.bootstrap.pagination', []) link: function(scope, element, attrs, paginationCtrl) { // Setup configuration parameters - var boundaryLinks = paginationCtrl.getAttributeValue(attrs.boundaryLinks, config.boundaryLinks ), - directionLinks = paginationCtrl.getAttributeValue(attrs.directionLinks, config.directionLinks ), - firstText = paginationCtrl.getAttributeValue(attrs.firstText, config.firstText, true), - previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true), - nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true), - lastText = paginationCtrl.getAttributeValue(attrs.lastText, config.lastText, true), - rotate = paginationCtrl.getAttributeValue(attrs.rotate, config.rotate); + var maxSize, + boundaryLinks = paginationCtrl.getAttributeValue(attrs.boundaryLinks, config.boundaryLinks ), + directionLinks = paginationCtrl.getAttributeValue(attrs.directionLinks, config.directionLinks ), + firstText = paginationCtrl.getAttributeValue(attrs.firstText, config.firstText, true), + previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true), + nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true), + lastText = paginationCtrl.getAttributeValue(attrs.lastText, config.lastText, true), + rotate = paginationCtrl.getAttributeValue(attrs.rotate, config.rotate); + + paginationCtrl.init(config.itemsPerPage); + + if (attrs.maxSize) { + scope.$parent.$watch($parse(attrs.maxSize), function(value) { + maxSize = parseInt(value, 10); + paginationCtrl.render(); + }); + } // Create page object used in template function makePage(number, text, isActive, isDisabled) { @@ -1723,76 +1764,79 @@ angular.module('ui.bootstrap.pagination', []) }; } - scope.$watch('numPages + currentPage + maxSize', function() { - paginationCtrl.reset(); + paginationCtrl.getPages = function(currentPage, totalPages) { + var pages = []; // Default page limits - var startPage = 1, endPage = scope.numPages; - var isMaxSized = ( angular.isDefined(scope.maxSize) && scope.maxSize < scope.numPages ); + var startPage = 1, endPage = totalPages; + var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages ); // recompute if maxSize if ( isMaxSized ) { if ( rotate ) { // Current page is displayed in the middle of the visible ones - startPage = Math.max(paginationCtrl.currentPage - Math.floor(scope.maxSize/2), 1); - endPage = startPage + scope.maxSize - 1; + startPage = Math.max(currentPage - Math.floor(maxSize/2), 1); + endPage = startPage + maxSize - 1; // Adjust if limit is exceeded - if (endPage > scope.numPages) { - endPage = scope.numPages; - startPage = endPage - scope.maxSize + 1; + if (endPage > totalPages) { + endPage = totalPages; + startPage = endPage - maxSize + 1; } } else { // Visible pages are paginated with maxSize - startPage = ((Math.ceil(paginationCtrl.currentPage / scope.maxSize) - 1) * scope.maxSize) + 1; + startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1; // Adjust last page if limit is exceeded - endPage = Math.min(startPage + scope.maxSize - 1, scope.numPages); + endPage = Math.min(startPage + maxSize - 1, totalPages); } } // Add page number links for (var number = startPage; number <= endPage; number++) { var page = makePage(number, number, paginationCtrl.isActive(number), false); - scope.pages.push(page); + pages.push(page); } // Add links to move between page sets if ( isMaxSized && ! rotate ) { if ( startPage > 1 ) { var previousPageSet = makePage(startPage - 1, '...', false, false); - scope.pages.unshift(previousPageSet); + pages.unshift(previousPageSet); } - if ( endPage < scope.numPages ) { + if ( endPage < totalPages ) { var nextPageSet = makePage(endPage + 1, '...', false, false); - scope.pages.push(nextPageSet); + pages.push(nextPageSet); } } // Add previous & next links if (directionLinks) { - var previousPage = makePage(paginationCtrl.currentPage - 1, previousText, false, paginationCtrl.noPrevious()); - scope.pages.unshift(previousPage); + var previousPage = makePage(currentPage - 1, previousText, false, paginationCtrl.noPrevious()); + pages.unshift(previousPage); - var nextPage = makePage(paginationCtrl.currentPage + 1, nextText, false, paginationCtrl.noNext()); - scope.pages.push(nextPage); + var nextPage = makePage(currentPage + 1, nextText, false, paginationCtrl.noNext()); + pages.push(nextPage); } // Add first & last links if (boundaryLinks) { var firstPage = makePage(1, firstText, false, paginationCtrl.noPrevious()); - scope.pages.unshift(firstPage); + pages.unshift(firstPage); - var lastPage = makePage(scope.numPages, lastText, false, paginationCtrl.noNext()); - scope.pages.push(lastPage); + var lastPage = makePage(totalPages, lastText, false, paginationCtrl.noNext()); + pages.push(lastPage); } - }); + + return pages; + }; } }; }]) .constant('pagerConfig', { + itemsPerPage: 10, previousText: '« Previous', nextText: 'Next »', align: true @@ -1802,9 +1846,10 @@ angular.module('ui.bootstrap.pagination', []) return { restrict: 'EA', scope: { - numPages: '=', - currentPage: '=', - onSelectPage: '&' + page: '=', + totalItems: '=', + onSelectPage:' &', + numPages: '=' }, controller: 'PaginationController', templateUrl: 'template/pagination/pager.html', @@ -1816,6 +1861,8 @@ angular.module('ui.bootstrap.pagination', []) nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true), align = paginationCtrl.getAttributeValue(attrs.align, config.align); + paginationCtrl.init(config.itemsPerPage); + // Create page object used in template function makePage(number, text, isDisabled, isPrevious, isNext) { return { @@ -1827,16 +1874,12 @@ angular.module('ui.bootstrap.pagination', []) }; } - scope.$watch('numPages + currentPage', function() { - paginationCtrl.reset(); - - // Add previous & next links - var previousPage = makePage(paginationCtrl.currentPage - 1, previousText, paginationCtrl.noPrevious(), true, false); - scope.pages.unshift(previousPage); - - var nextPage = makePage(paginationCtrl.currentPage + 1, nextText, paginationCtrl.noNext(), false, true); - scope.pages.push(nextPage); - }); + paginationCtrl.getPages = function(currentPage) { + return [ + makePage(currentPage - 1, previousText, paginationCtrl.noPrevious(), true, false), + makePage(currentPage + 1, nextText, paginationCtrl.noNext(), false, true) + ]; + }; } }; }]); @@ -1846,7 +1889,7 @@ angular.module('ui.bootstrap.pagination', []) * function, placement as a function, inside, support for more triggers than * just mouse enter/leave, html tooltips, and selector delegation. */ -angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position' ] ) +angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] ) /** * The $tooltip service creates tooltip- and popover-like directives as well as @@ -2027,13 +2070,6 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position' ] ) // Calculate the tooltip's top and left coordinates to center it with // this directive. switch ( scope.tt_placement ) { - case 'mouse': - var mousePos = $position.mouse(); - ttPosition = { - top: mousePos.y, - left: mousePos.x - }; - break; case 'right': ttPosition = { top: position.top + position.height / 2 - ttHeight / 2, @@ -2314,60 +2350,86 @@ angular.module('ui.bootstrap.progressbar', ['ui.bootstrap.transition']) angular.module('ui.bootstrap.rating', []) .constant('ratingConfig', { - max: 5 + max: 5, + stateOn: null, + stateOff: null }) -.directive('rating', ['ratingConfig', '$parse', function(ratingConfig, $parse) { - return { - restrict: 'EA', - scope: { - value: '=', - onHover: '&', - onLeave: '&' - }, - templateUrl: 'template/rating/rating.html', - replace: true, - link: function(scope, element, attrs) { +.controller('RatingController', ['$scope', '$attrs', '$parse', 'ratingConfig', function($scope, $attrs, $parse, ratingConfig) { - var maxRange = angular.isDefined(attrs.max) ? scope.$parent.$eval(attrs.max) : ratingConfig.max; + this.maxRange = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max; + this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; + this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; - scope.range = []; - for (var i = 1; i <= maxRange; i++) { - scope.range.push(i); - } + this.createDefaultRange = function(len) { + var defaultStateObject = { + stateOn: this.stateOn, + stateOff: this.stateOff + }; - scope.rate = function(value) { - if ( ! scope.readonly ) { - scope.value = value; - } - }; + var states = new Array(len); + for (var i = 0; i < len; i++) { + states[i] = defaultStateObject; + } + return states; + }; - scope.enter = function(value) { - if ( ! scope.readonly ) { - scope.val = value; - } - scope.onHover({value: value}); - }; + this.normalizeRange = function(states) { + for (var i = 0, n = states.length; i < n; i++) { + states[i].stateOn = states[i].stateOn || this.stateOn; + states[i].stateOff = states[i].stateOff || this.stateOff; + } + return states; + }; - scope.reset = function() { - scope.val = angular.copy(scope.value); - scope.onLeave(); - }; - scope.reset(); + // Get objects used in template + $scope.range = angular.isDefined($attrs.ratingStates) ? this.normalizeRange(angular.copy($scope.$parent.$eval($attrs.ratingStates))): this.createDefaultRange(this.maxRange); - scope.$watch('value', function(value) { - scope.val = value; - }); + $scope.rate = function(value) { + if ( $scope.readonly || $scope.value === value) { + return; + } - scope.readonly = false; - if (attrs.readonly) { - scope.$parent.$watch($parse(attrs.readonly), function(value) { - scope.readonly = !!value; - }); - } + $scope.value = value; + }; + + $scope.enter = function(value) { + if ( ! $scope.readonly ) { + $scope.val = value; } + $scope.onHover({value: value}); }; -}]); + + $scope.reset = function() { + $scope.val = angular.copy($scope.value); + $scope.onLeave(); + }; + + $scope.$watch('value', function(value) { + $scope.val = value; + }); + + $scope.readonly = false; + if ($attrs.readonly) { + $scope.$parent.$watch($parse($attrs.readonly), function(value) { + $scope.readonly = !!value; + }); + } +}]) + +.directive('rating', function() { + return { + restrict: 'EA', + scope: { + value: '=', + onHover: '&', + onLeave: '&' + }, + controller: 'RatingController', + templateUrl: 'template/rating/rating.html', + replace: true + }; +}); /** * @ngdoc overview @@ -2455,7 +2517,7 @@ function TabsetCtrl($scope, $element) { templateUrl: 'template/tabs/tabset.html', compile: function(elm, attrs, transclude) { return function(scope, element, attrs, tabsetCtrl) { - scope.vertical = angular.isDefined(attrs.vertical) ? scope.$eval(attrs.vertical) : false; + scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; scope.type = angular.isDefined(attrs.type) ? scope.$parent.$eval(attrs.type) : 'tabs'; scope.direction = angular.isDefined(attrs.direction) ? scope.$parent.$eval(attrs.direction) : 'top'; scope.tabsAbove = (scope.direction != 'below'); @@ -2663,7 +2725,7 @@ function($parse, $http, $templateCache, $compile) { } }]) -.directive('tabsetTitles', function($http) { +.directive('tabsetTitles', ['$http', function($http) { return { restrict: 'A', require: '^tabset', @@ -2680,22 +2742,13 @@ function($parse, $http, $templateCache, $compile) { } } }; -}) +}]) ; angular.module('ui.bootstrap.timepicker', []) -.filter('pad', function() { - return function(input) { - if ( angular.isDefined(input) && input.toString().length < 2 ) { - input = '0' + input; - } - return input; - }; -}) - .constant('timepickerConfig', { hourStep: 1, minuteStep: 1, @@ -2705,16 +2758,18 @@ angular.module('ui.bootstrap.timepicker', []) mousewheel: true }) -.directive('timepicker', ['padFilter', '$parse', 'timepickerConfig', function (padFilter, $parse, timepickerConfig) { +.directive('timepicker', ['$parse', '$log', 'timepickerConfig', function ($parse, $log, timepickerConfig) { return { restrict: 'EA', - require:'ngModel', + require:'?^ngModel', replace: true, + scope: {}, templateUrl: 'template/timepicker/timepicker.html', - scope: { - model: '=ngModel' - }, - link: function(scope, element, attrs, ngModelCtrl) { + link: function(scope, element, attrs, ngModel) { + if ( !ngModel ) { + return; // do nothing if no ng-model + } + var selected = new Date(), meridians = timepickerConfig.meridians; var hourStep = timepickerConfig.hourStep; @@ -2735,28 +2790,27 @@ angular.module('ui.bootstrap.timepicker', []) scope.showMeridian = timepickerConfig.showMeridian; if (attrs.showMeridian) { scope.$parent.$watch($parse(attrs.showMeridian), function(value) { - scope.showMeridian = !! value; - - if ( ! scope.model ) { - // Reset - var dt = new Date( selected ); - var hours = getScopeHours(); - if (angular.isDefined( hours )) { - dt.setHours( hours ); + scope.showMeridian = !!value; + + if ( ngModel.$error.time ) { + // Evaluate from template + var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); + if (angular.isDefined( hours ) && angular.isDefined( minutes )) { + selected.setHours( hours ); + refresh(); } - scope.model = new Date( dt ); } else { - refreshTemplate(); + updateTemplate(); } }); } // Get scope.hours in 24H mode if valid - function getScopeHours ( ) { + function getHoursFromTemplate ( ) { var hours = parseInt( scope.hours, 10 ); var valid = ( scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24); if ( !valid ) { - return; + return undefined; } if ( scope.showMeridian ) { @@ -2770,14 +2824,22 @@ angular.module('ui.bootstrap.timepicker', []) return hours; } + function getMinutesFromTemplate() { + var minutes = parseInt(scope.minutes, 10); + return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined; + } + + function pad( value ) { + return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value; + } + // Input elements - var inputs = element.find('input'); - var hoursInputEl = inputs.eq(0), minutesInputEl = inputs.eq(1); + var inputs = element.find('input'), hoursInputEl = inputs.eq(0), minutesInputEl = inputs.eq(1); // Respond on mousewheel spin var mousewheel = (angular.isDefined(attrs.mousewheel)) ? scope.$eval(attrs.mousewheel) : timepickerConfig.mousewheel; if ( mousewheel ) { - + var isScrollingUp = function(e) { if (e.originalEvent) { e = e.originalEvent; @@ -2786,7 +2848,7 @@ angular.module('ui.bootstrap.timepicker', []) var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY; return (e.detail || delta > 0); }; - + hoursInputEl.bind('mousewheel wheel', function(e) { scope.$apply( (isScrollingUp(e)) ? scope.incrementHours() : scope.decrementHours() ); e.preventDefault(); @@ -2798,50 +2860,54 @@ angular.module('ui.bootstrap.timepicker', []) }); } - var keyboardChange = false; scope.readonlyInput = (angular.isDefined(attrs.readonlyInput)) ? scope.$eval(attrs.readonlyInput) : timepickerConfig.readonlyInput; if ( ! scope.readonlyInput ) { + + var invalidate = function(invalidHours, invalidMinutes) { + ngModel.$setViewValue( null ); + ngModel.$setValidity('time', false); + if (angular.isDefined(invalidHours)) { + scope.invalidHours = invalidHours; + } + if (angular.isDefined(invalidMinutes)) { + scope.invalidMinutes = invalidMinutes; + } + }; + scope.updateHours = function() { - var hours = getScopeHours(); + var hours = getHoursFromTemplate(); if ( angular.isDefined(hours) ) { - keyboardChange = 'h'; - if ( scope.model === null ) { - scope.model = new Date( selected ); - } - scope.model.setHours( hours ); + selected.setHours( hours ); + refresh( 'h' ); } else { - scope.model = null; - scope.validHours = false; + invalidate(true); } }; hoursInputEl.bind('blur', function(e) { - if ( scope.validHours && scope.hours < 10) { + if ( !scope.validHours && scope.hours < 10) { scope.$apply( function() { - scope.hours = padFilter( scope.hours ); + scope.hours = pad( scope.hours ); }); } }); scope.updateMinutes = function() { - var minutes = parseInt(scope.minutes, 10); - if ( minutes >= 0 && minutes < 60 ) { - keyboardChange = 'm'; - if ( scope.model === null ) { - scope.model = new Date( selected ); - } - scope.model.setMinutes( minutes ); + var minutes = getMinutesFromTemplate(); + + if ( angular.isDefined(minutes) ) { + selected.setMinutes( minutes ); + refresh( 'm' ); } else { - scope.model = null; - scope.validMinutes = false; + invalidate(undefined, true); } }; minutesInputEl.bind('blur', function(e) { - if ( scope.validMinutes && scope.minutes < 10 ) { + if ( !scope.invalidMinutes && scope.minutes < 10 ) { scope.$apply( function() { - scope.minutes = padFilter( scope.minutes ); + scope.minutes = pad( scope.minutes ); }); } }); @@ -2850,38 +2916,49 @@ angular.module('ui.bootstrap.timepicker', []) scope.updateMinutes = angular.noop; } - scope.$watch( function getModelTimestamp() { - return +scope.model; - }, function( timestamp ) { - if ( !isNaN( timestamp ) && timestamp > 0 ) { - selected = new Date( timestamp ); - refreshTemplate(); - } - }); + ngModel.$render = function() { + var date = ngModel.$modelValue ? new Date( ngModel.$modelValue ) : null; - function refreshTemplate() { - var hours = selected.getHours(); - if ( scope.showMeridian ) { - // Convert 24 to 12 hour system - hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; + if ( isNaN(date) ) { + ngModel.$setValidity('time', false); + $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.'); + } else { + if ( date ) { + selected = date; + } + makeValid(); + updateTemplate(); } - scope.hours = ( keyboardChange === 'h' ) ? hours : padFilter(hours); - scope.validHours = true; + }; + + // Call internally when we know that model is valid. + function refresh( keyboardChange ) { + makeValid(); + ngModel.$setViewValue( new Date(selected) ); + updateTemplate( keyboardChange ); + } - var minutes = selected.getMinutes(); - scope.minutes = ( keyboardChange === 'm' ) ? minutes : padFilter(minutes); - scope.validMinutes = true; + function makeValid() { + ngModel.$setValidity('time', true); + scope.invalidHours = false; + scope.invalidMinutes = false; + } - scope.meridian = ( scope.showMeridian ) ? (( selected.getHours() < 12 ) ? meridians[0] : meridians[1]) : ''; + function updateTemplate( keyboardChange ) { + var hours = selected.getHours(), minutes = selected.getMinutes(); - keyboardChange = false; + if ( scope.showMeridian ) { + hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system + } + scope.hours = keyboardChange === 'h' ? hours : pad(hours); + scope.minutes = keyboardChange === 'm' ? minutes : pad(minutes); + scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; } function addMinutes( minutes ) { var dt = new Date( selected.getTime() + minutes * 60000 ); - selected.setHours( dt.getHours() ); - selected.setMinutes( dt.getMinutes() ); - scope.model = new Date( selected ); + selected.setHours( dt.getHours(), dt.getMinutes() ); + refresh(); } scope.incrementHours = function() { @@ -2903,7 +2980,7 @@ angular.module('ui.bootstrap.timepicker', []) }; }]); -angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) +angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml']) /** * A helper service that can parse typeahead's syntax (string provided by users) @@ -2934,7 +3011,8 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) }; }]) - .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser', function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) { + .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser', + function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) { var HOT_KEYS = [9, 13, 27, 38, 40]; @@ -3047,7 +3125,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue - modelCtrl.$parsers.push(function (inputValue) { + modelCtrl.$parsers.unshift(function (inputValue) { resetMatches(); if (inputValue && inputValue.length >= minSearch) { @@ -3063,7 +3141,12 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) } } - return isEditable ? inputValue : undefined; + if (isEditable) { + return inputValue; + } else { + modelCtrl.$setValidity('editable', false); + return undefined; + } }); modelCtrl.$formatters.push(function (modelValue) { @@ -3077,12 +3160,13 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) return inputFormatter(originalScope, locals); } else { - locals[parserResult.itemName] = modelValue; //it might happen that we don't have enough info to properly render input value //we need to check for this situation and simply return model value if we can't apply custom formatting + locals[parserResult.itemName] = modelValue; candidateViewValue = parserResult.viewMapper(originalScope, locals); - emptyViewValue = parserResult.viewMapper(originalScope, {}); + locals[parserResult.itemName] = undefined; + emptyViewValue = parserResult.viewMapper(originalScope, locals); return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue; } @@ -3096,6 +3180,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) locals[parserResult.itemName] = item = scope.matches[activeIdx].model; model = parserResult.modelMapper(originalScope, locals); $setModelValue(originalScope, model); + modelCtrl.$setValidity('editable', true); onSelectCallback(originalScope, { $item: item, @@ -3103,8 +3188,9 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) $label: parserResult.viewMapper(originalScope, locals) }); - //return focus to the input element if a mach was selected via a mouse click event resetMatches(); + + //return focus to the input element if a mach was selected via a mouse click event element[0].focus(); }; @@ -3139,9 +3225,18 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) } }); - $document.bind('click', function(){ - resetMatches(); - scope.$digest(); + // Keep reference to click handler to unbind it. + var dismissClickHandler = function (evt) { + if (element[0] !== evt.target) { + resetMatches(); + scope.$digest(); + } + }; + + $document.bind('click', dismissClickHandler); + + originalScope.$on('$destroy', function(){ + $document.unbind('click', dismissClickHandler); }); element.after($compile(popUpEl)(scope)); @@ -3209,7 +3304,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) } return function(matchItem, query) { - return query ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : query; + return query ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; }; }); angular.module("template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) { @@ -3302,28 +3397,14 @@ angular.module("template/datepicker/popup.html", []).run(["$templateCache", func ""); }]); -angular.module("template/dialog/message.html", []).run(["$templateCache", function($templateCache) { - $templateCache.put("template/dialog/message.html", - "
\n" + - "

{{ title }}

\n" + - "
\n" + - "
\n" + - "

{{ message }}

\n" + - "
\n" + - "
\n" + - " \n" + - "
\n" + - ""); -}]); - angular.module("template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("template/modal/backdrop.html", - "
"); + "
"); }]); angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("template/modal/window.html", - "
"); + "
"); }]); angular.module("template/pagination/pager.html", []).run(["$templateCache", function($templateCache) { @@ -3389,7 +3470,7 @@ angular.module("template/progressbar/progress.html", []).run(["$templateCache", angular.module("template/rating/rating.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("template/rating/rating.html", "\n" + - " val}\">\n" + + " \n" + ""); }]); @@ -3454,10 +3535,10 @@ angular.module("template/timepicker/timepicker.html", []).run(["$templateCache", " \n" + " \n" + " \n" + - " \n" + + " \n" + " :\n" + - " \n" + - " \n" + + " \n" + + " \n" + " \n" + " \n" + " \n" + @@ -3470,7 +3551,7 @@ angular.module("template/timepicker/timepicker.html", []).run(["$templateCache", angular.module("template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) { $templateCache.put("template/typeahead/typeahead-match.html", - ""); + ""); }]); angular.module("template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) { diff --git a/ui-bootstrap-tpls.min.js b/ui-bootstrap-tpls.min.js index 9d3d10e..2ac1a9d 100644 --- a/ui-bootstrap-tpls.min.js +++ b/ui-bootstrap-tpls.min.js @@ -1,2 +1,2 @@ -angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dialog","ui.bootstrap.dropdownToggle","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"]),angular.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/popup.html","template/dialog/message.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset-titles.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(e,t,n){function a(e){for(var t in e)if(void 0!==o.style[t])return e[t]}var i=function(a,o,r){r=r||{};var l=e.defer(),s=i[r.animation?"animationEndEventName":"transitionEndEventName"],c=function(){n.$apply(function(){a.unbind(s,c),l.resolve(a)})};return s&&a.bind(s,c),t(function(){angular.isString(o)?a.addClass(o):angular.isFunction(o)?o(a):angular.isObject(o)&&a.css(o),s||l.resolve(a)}),l.promise.cancel=function(){s&&a.unbind(s,c),l.reject("Transition cancelled")},l.promise},o=document.createElement("trans"),r={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},l={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return i.transitionEndEventName=a(r),i.animationEndEventName=a(l),i}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(e){var t=function(e,t,n){t.removeClass("collapse"),t.css({height:n}),t[0].offsetWidth,t.addClass("collapse")};return{link:function(n,a,i){var o,r=!0;n.$watch(function(){return a[0].scrollHeight},function(){0!==a[0].scrollHeight&&(o||(r?t(n,a,a[0].scrollHeight+"px"):t(n,a,"auto")))}),n.$watch(i.collapse,function(e){e?u():c()});var l,s=function(t){return l&&l.cancel(),l=e(a,t),l.then(function(){l=void 0},function(){l=void 0}),l},c=function(){r?(r=!1,o||t(n,a,"auto")):s({height:a[0].scrollHeight+"px"}).then(function(){o||t(n,a,"auto")}),o=!1},u=function(){o=!0,r?(r=!1,t(n,a,0)):(t(n,a,a[0].scrollHeight+"px"),s({height:"0"}))}}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(e,t,n){this.groups=[],this.closeOthers=function(a){var i=angular.isDefined(t.closeOthers)?e.$eval(t.closeOthers):n.closeOthers;i&&angular.forEach(this.groups,function(e){e!==a&&(e.isOpen=!1)})},this.addGroup=function(e){var t=this;this.groups.push(e),e.$on("$destroy",function(){t.removeGroup(e)})},this.removeGroup=function(e){var t=this.groups.indexOf(e);-1!==t&&this.groups.splice(this.groups.indexOf(e),1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",["$parse","$transition","$timeout",function(e){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@"},controller:["$scope",function(){this.setHeading=function(e){this.heading=e}}],link:function(t,n,a,i){var o,r;i.addGroup(t),t.isOpen=!1,a.isOpen&&(o=e(a.isOpen),r=o.assign,t.$watch(function(){return o(t.$parent)},function(e){t.isOpen=e}),t.isOpen=o?o(t.$parent):!1),t.$watch("isOpen",function(e){e&&i.closeOthers(t),r&&r(t.$parent,e)})}}}]).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",compile:function(e,t,n){return function(e,t,a,i){i.setHeading(n(e,function(){}))}}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(e,t,n,a){e.$watch(function(){return a[n.accordionTransclude]},function(e){e&&(t.html(""),t.append(e))})}}}),angular.module("ui.bootstrap.alert",[]).directive("alert",function(){return{restrict:"EA",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"=",close:"&"},link:function(e,t,n){e.closeable="close"in n}}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).directive("btnRadio",["buttonConfig",function(e){var t=e.activeClass||"active",n=e.toggleEvent||"click";return{require:"ngModel",link:function(e,a,i,o){o.$render=function(){a.toggleClass(t,angular.equals(o.$modelValue,e.$eval(i.btnRadio)))},a.bind(n,function(){a.hasClass(t)||e.$apply(function(){o.$setViewValue(e.$eval(i.btnRadio)),o.$render()})})}}}]).directive("btnCheckbox",["buttonConfig",function(e){var t=e.activeClass||"active",n=e.toggleEvent||"click";return{require:"ngModel",link:function(e,a,i,o){function r(){var t=e.$eval(i.btnCheckboxTrue);return angular.isDefined(t)?t:!0}function l(){var t=e.$eval(i.btnCheckboxFalse);return angular.isDefined(t)?t:!1}o.$render=function(){a.toggleClass(t,angular.equals(o.$modelValue,r()))},a.bind(n,function(){e.$apply(function(){o.$setViewValue(a.hasClass(t)?l():r()),o.$render()})})}}}]),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$transition","$q",function(e,t,n){function a(){function n(){o?(e.next(),a()):e.pause()}i&&t.cancel(i);var r=+e.interval;!isNaN(r)&&r>=0&&(i=t(n,r))}var i,o,r=this,l=r.slides=[],s=-1;r.currentSlide=null,r.select=function(i,o){function c(){r.currentSlide&&angular.isString(o)&&!e.noTransition&&i.$element?(i.$element.addClass(o),i.$element[0].offsetWidth=i.$element[0].offsetWidth,angular.forEach(l,function(e){angular.extend(e,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(i,{direction:o,active:!0,entering:!0}),angular.extend(r.currentSlide||{},{direction:o,leaving:!0}),e.$currentTransition=n(i.$element,{}),function(t,n){e.$currentTransition.then(function(){u(t,n)},function(){u(t,n)})}(i,r.currentSlide)):u(i,r.currentSlide),r.currentSlide=i,s=p,a()}function u(t,n){angular.extend(t,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(n||{},{direction:"",active:!1,leaving:!1,entering:!1}),e.$currentTransition=null}var p=l.indexOf(i);void 0===o&&(o=p>s?"next":"prev"),i&&i!==r.currentSlide&&(e.$currentTransition?(e.$currentTransition.cancel(),t(c)):c())},r.indexOfSlide=function(e){return l.indexOf(e)},e.next=function(){var t=(s+1)%l.length;return e.$currentTransition?void 0:r.select(l[t],"next")},e.prev=function(){var t=0>s-1?l.length-1:s-1;return e.$currentTransition?void 0:r.select(l[t],"prev")},e.select=function(e){r.select(e)},e.isActive=function(e){return r.currentSlide===e},e.slides=function(){return l},e.$watch("interval",a),e.play=function(){o||(o=!0,a())},e.pause=function(){e.noPause||(o=!1,i&&t.cancel(i))},r.addSlide=function(t,n){t.$element=n,l.push(t),1===l.length||t.active?(r.select(l[l.length-1]),1==l.length&&e.play()):t.active=!1},r.removeSlide=function(e){var t=l.indexOf(e);l.splice(t,1),l.length>0&&e.active?t>=l.length?r.select(l[t-1]):r.select(l[t]):s>t&&s--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",["$parse",function(e){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{},link:function(t,n,a,i){if(a.active){var o=e(a.active),r=o.assign,l=t.active=o(t.$parent);t.$watch(function(){var e=o(t.$parent);return e!==t.active&&(e!==l?l=t.active=e:r(t.$parent,e=l=t.active)),e})}i.addSlide(t,n),t.$on("$destroy",function(){i.removeSlide(t)}),t.$watch("active",function(e){e&&i.select(t)})}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(e,t){function n(e,n){return e.currentStyle?e.currentStyle[n]:t.getComputedStyle?t.getComputedStyle(e)[n]:e.style[n]}function a(e){return"static"===(n(e,"position")||"static")}var i,o;e.bind("mousemove",function(e){i=e.pageX,o=e.pageY});var r=function(t){for(var n=e[0],i=t.offsetParent||n;i&&i!==n&&a(i);)i=i.offsetParent;return i||n};return{position:function(t){var n=this.offset(t),a={top:0,left:0},i=r(t[0]);return i!=e[0]&&(a=this.offset(angular.element(i)),a.top+=i.clientTop-i.scrollTop,a.left+=i.clientLeft-i.scrollLeft),{width:t.prop("offsetWidth"),height:t.prop("offsetHeight"),top:n.top-a.top,left:n.left-a.left}},offset:function(n){var a=n[0].getBoundingClientRect();return{width:n.prop("offsetWidth"),height:n.prop("offsetHeight"),top:a.top+(t.pageYOffset||e[0].body.scrollTop),left:a.left+(t.pageXOffset||e[0].body.scrollLeft)}},mouse:function(){return{x:i,y:o}}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.position"]).constant("datepickerConfig",{dayFormat:"dd",monthFormat:"MMMM",yearFormat:"yyyy",dayHeaderFormat:"EEE",dayTitleFormat:"MMMM yyyy",monthTitleFormat:"yyyy",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","dateFilter","datepickerConfig",function(e,t,n,a){function i(t,n){return angular.isDefined(t)?e.$parent.$eval(t):n}function o(e,t){return new Date(e,t,0).getDate()}function r(e,t){for(var n=Array(t),a=e,i=0;t>i;)n[i++]=new Date(a),a.setDate(a.getDate()+1);return n}function l(e,t,a,i){return{date:e,label:n(e,t),selected:!!a,secondary:!!i}}var s={day:i(t.dayFormat,a.dayFormat),month:i(t.monthFormat,a.monthFormat),year:i(t.yearFormat,a.yearFormat),dayHeader:i(t.dayHeaderFormat,a.dayHeaderFormat),dayTitle:i(t.dayTitleFormat,a.dayTitleFormat),monthTitle:i(t.monthTitleFormat,a.monthTitleFormat)},c=i(t.startingDay,a.startingDay),u=i(t.yearRange,a.yearRange);this.minDate=a.minDate?new Date(a.minDate):null,this.maxDate=a.maxDate?new Date(a.maxDate):null,this.modes=[{name:"day",getVisibleDates:function(e,t){var a=e.getFullYear(),i=e.getMonth(),u=new Date(a,i,1),p=c-u.getDay(),d=p>0?7-p:-p,m=new Date(u),g=0;d>0&&(m.setDate(-d+1),g+=d),g+=o(a,i+1),g+=(7-g%7)%7;for(var f=r(m,g),h=Array(7),v=0;g>v;v++){var b=new Date(f[v]);f[v]=l(b,s.day,t&&t.getDate()===b.getDate()&&t.getMonth()===b.getMonth()&&t.getFullYear()===b.getFullYear(),b.getMonth()!==i)}for(var $=0;7>$;$++)h[$]=n(f[$].date,s.dayHeader);return{objects:f,title:n(e,s.dayTitle),labels:h}},compare:function(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate())-new Date(t.getFullYear(),t.getMonth(),t.getDate())},split:7,step:{months:1}},{name:"month",getVisibleDates:function(e,t){for(var a=Array(12),i=e.getFullYear(),o=0;12>o;o++){var r=new Date(i,o,1);a[o]=l(r,s.month,t&&t.getMonth()===o&&t.getFullYear()===i)}return{objects:a,title:n(e,s.monthTitle)}},compare:function(e,t){return new Date(e.getFullYear(),e.getMonth())-new Date(t.getFullYear(),t.getMonth())},split:3,step:{years:1}},{name:"year",getVisibleDates:function(e,t){for(var n=Array(u),a=e.getFullYear(),i=parseInt((a-1)/u,10)*u+1,o=0;u>o;o++){var r=new Date(i+o,0,1);n[o]=l(r,s.year,t&&t.getFullYear()===r.getFullYear())}return{objects:n,title:[n[0].label,n[u-1].label].join(" - ")}},compare:function(e,t){return e.getFullYear()-t.getFullYear()},split:5,step:{years:u}}],this.isDisabled=function(t,n){var a=this.modes[n||0];return this.minDate&&0>a.compare(t,this.minDate)||this.maxDate&&a.compare(t,this.maxDate)>0||e.dateDisabled&&e.dateDisabled({date:t,mode:a.name})}}]).directive("datepicker",["dateFilter","$parse","datepickerConfig","$log",function(e,t,n,a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(e,i,o,r){function l(){e.showWeekNumbers=0===g&&h}function s(e,t){for(var n=[];e.length>0;)n.push(e.splice(0,t));return n}function c(t){var n=null,i=!0;m.$modelValue&&(n=new Date(m.$modelValue),isNaN(n)?(i=!1,a.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.')):t&&(f=n)),m.$setValidity("date",i);var o=d.modes[g],r=o.getVisibleDates(f,n);angular.forEach(r.objects,function(e){e.disabled=d.isDisabled(e.date,g)}),m.$setValidity("date-disabled",!n||!d.isDisabled(n)),e.rows=s(r.objects,o.split),e.labels=r.labels||[],e.title=r.title}function u(e){g=e,l(),c()}function p(e){var t=new Date(e);t.setDate(t.getDate()+4-(t.getDay()||7));var n=t.getTime();return t.setMonth(0),t.setDate(1),Math.floor(Math.round((n-t)/864e5)/7)+1}var d=r[0],m=r[1];if(m){var g=0,f=new Date,h=n.showWeeks;o.showWeeks?e.$parent.$watch(t(o.showWeeks),function(e){h=!!e,l()}):l(),o.min&&e.$parent.$watch(t(o.min),function(e){d.minDate=e?new Date(e):null,c()}),o.max&&e.$parent.$watch(t(o.max),function(e){d.maxDate=e?new Date(e):null,c()}),m.$render=function(){c(!0)},e.select=function(e){if(0===g){var t=new Date(m.$modelValue);t.setFullYear(e.getFullYear(),e.getMonth(),e.getDate()),m.$setViewValue(t),c(!0)}else f=e,u(g-1)},e.move=function(e){var t=d.modes[g].step;f.setMonth(f.getMonth()+e*(t.months||0)),f.setFullYear(f.getFullYear()+e*(t.years||0)),c()},e.toggleMode=function(){u((g+1)%d.modes.length)},e.getWeekNumber=function(t){return 0===g&&e.showWeekNumbers&&7===t.length?p(t[0].date):null}}}}}]).constant("datepickerPopupConfig",{dateFormat:"yyyy-MM-dd",closeOnDateSelection:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","datepickerPopupConfig",function(e,t,n,a,i,o){return{restrict:"EA",require:"ngModel",link:function(r,l,s,c){function u(e){return e?i(e,h):null}function p(e){if(e){var t=new Date(e);if(!isNaN(t))return t}return e}function d(e){$?$(r,!!e):v.isOpen=!!e}function m(e,n,a){e&&(r.$watch(t(e),function(e){v[n]=e}),D.attr(a||n,n))}function g(){v.position=a.position(l),v.position.top=v.position.top+l.prop("offsetHeight")}var f=angular.isDefined(s.closeOnDateSelection)?v.$eval(s.closeOnDateSelection):o.closeOnDateSelection,h=s.datepickerPopup||o.dateFormat,v=r.$new();r.$on("$destroy",function(){v.$destroy()}),c.$formatters.push(u),c.$parsers.push(p);var b,$;s.open&&(b=t(s.open),$=b.assign,r.$watch(b,function(e){v.isOpen=!!e})),v.isOpen=b?b(r):!1;var y=function(e){v.isOpen&&e.target!==l[0]&&v.$apply(function(){d(!1)})},w=function(){v.$apply(function(){d(!0)})},k=angular.element("");k.attr({"ng-model":"date","ng-change":"dateSelection()"});var D=k.find("datepicker");s.datepickerOptions&&D.attr(angular.extend({},r.$eval(s.datepickerOptions)));var x=t(s.ngModel).assign;v.dateSelection=function(){x(r,v.date),f&&d(!1)},v.$watch(function(){return c.$modelValue},function(e){if(angular.isString(e)){var t=p(e);if(e&&!t)throw x(r,null),Error(e+" cannot be parsed to a date object.");e=t}v.date=e,g()}),m(s.min,"min"),m(s.max,"max"),s.showWeeks?m(s.showWeeks,"showWeeks","show-weeks"):(v.showWeeks=!0,D.attr("show-weeks","showWeeks")),s.dateDisabled&&D.attr("date-disabled",s.dateDisabled),v.$watch("isOpen",function(e){e?(g(),n.bind("click",y),l.unbind("focus",w),l.focus()):(n.unbind("click",y),l.bind("focus",w)),$&&$(r,e)}),v.today=function(){x(r,new Date)},v.clear=function(){x(r,null)},l.after(e(k)(v))}}}]).directive("datepickerPopupWrap",[function(){return{restrict:"E",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(e,t){t.bind("click",function(e){e.preventDefault(),e.stopPropagation()})}}}]);var dialogModule=angular.module("ui.bootstrap.dialog",["ui.bootstrap.transition"]);dialogModule.controller("MessageBoxController",["$scope","dialog","model",function(e,t,n){e.title=n.title,e.message=n.message,e.buttons=n.buttons,e.close=function(e){t.close(e)}}]),dialogModule.provider("$dialog",function(){var e={backdrop:!0,dialogClass:"modal",backdropClass:"modal-backdrop",transitionClass:"fade",triggerClass:"in",resolve:{},backdropFade:!1,dialogFade:!1,keyboard:!0,backdropClick:!0},t={},n={value:0};this.options=function(e){t=e},this.$get=["$http","$document","$compile","$rootScope","$controller","$templateCache","$q","$transition","$injector",function(a,i,o,r,l,s,c,u,p){function d(e){var t=angular.element("
");return t.addClass(e),t}function m(n){var a=this,i=this.options=angular.extend({},e,t,n);this._open=!1,this.backdropEl=d(i.backdropClass),i.backdropFade&&(this.backdropEl.addClass(i.transitionClass),this.backdropEl.removeClass(i.triggerClass)),this.modalEl=d(i.dialogClass),i.dialogFade&&(this.modalEl.addClass(i.transitionClass),this.modalEl.removeClass(i.triggerClass)),this.handledEscapeKey=function(e){27===e.which&&(a.close(),e.preventDefault(),a.$scope.$apply())},this.handleBackDropClick=function(e){a.close(),e.preventDefault(),a.$scope.$apply()}}var g=i.find("body");return m.prototype.isOpen=function(){return this._open},m.prototype.open=function(e,t){var n=this,a=this.options;if(e&&(a.templateUrl=e),t&&(a.controller=t),!a.template&&!a.templateUrl)throw Error("Dialog.open expected template or templateUrl, neither found. Use options or open method to specify them.");return this._loadResolves().then(function(e){var t=e.$scope=n.$scope=e.$scope?e.$scope:r.$new();if(n.modalEl.html(e.$template),n.options.controller){var a=l(n.options.controller,e);n.modalEl.children().data("ngControllerController",a)}o(n.modalEl)(t),n._addElementsToDom(),setTimeout(function(){n.options.dialogFade&&n.modalEl.addClass(n.options.triggerClass),n.options.backdropFade&&n.backdropEl.addClass(n.options.triggerClass)}),n._bindEvents()}),this.deferred=c.defer(),this.deferred.promise},m.prototype.close=function(e){function t(e){e.removeClass(a.options.triggerClass)}function n(){a._open&&a._onCloseComplete(e)}var a=this,i=this._getFadingElements();if(i.length>0)for(var o=i.length-1;o>=0;o--)u(i[o],t).then(n);else this._onCloseComplete(e)},m.prototype._getFadingElements=function(){var e=[];return this.options.dialogFade&&e.push(this.modalEl),this.options.backdropFade&&e.push(this.backdropEl),e},m.prototype._bindEvents=function(){this.options.keyboard&&g.bind("keydown",this.handledEscapeKey),this.options.backdrop&&this.options.backdropClick&&this.backdropEl.bind("click",this.handleBackDropClick)},m.prototype._unbindEvents=function(){this.options.keyboard&&g.unbind("keydown",this.handledEscapeKey),this.options.backdrop&&this.options.backdropClick&&this.backdropEl.unbind("click",this.handleBackDropClick)},m.prototype._onCloseComplete=function(e){this._removeElementsFromDom(),this._unbindEvents(),this.deferred.resolve(e)},m.prototype._addElementsToDom=function(){g.append(this.modalEl),this.options.backdrop&&(0===n.value&&g.append(this.backdropEl),n.value++),this._open=!0},m.prototype._removeElementsFromDom=function(){this.modalEl.remove(),this.options.backdrop&&(n.value--,0===n.value&&this.backdropEl.remove()),this._open=!1},m.prototype._loadResolves=function(){var e,t=[],n=[],i=this;return this.options.template?e=c.when(this.options.template):this.options.templateUrl&&(e=a.get(this.options.templateUrl,{cache:s}).then(function(e){return e.data})),angular.forEach(this.options.resolve||[],function(e,a){n.push(a),t.push(angular.isString(e)?p.get(e):p.invoke(e))}),n.push("$template"),t.push(e),c.all(t).then(function(e){var t={};return angular.forEach(e,function(e,a){t[n[a]]=e}),t.dialog=i,t})},{dialog:function(e){return new m(e)},messageBox:function(e,t,n){return new m({templateUrl:"template/dialog/message.html",controller:"MessageBoxController",resolve:{model:function(){return{title:e,message:t,buttons:n}}}})}}}]}),angular.module("ui.bootstrap.dropdownToggle",[]).directive("dropdownToggle",["$document","$location",function(e){var t=null,n=angular.noop;return{restrict:"CA",link:function(a,i){a.$watch("$location.path",function(){n()}),i.parent().bind("click",function(){n()}),i.bind("click",function(a){var o=i===t;a.preventDefault(),a.stopPropagation(),t&&n(),o||(i.parent().addClass("open"),t=i,n=function(a){a&&(a.preventDefault(),a.stopPropagation()),e.unbind("click",n),i.parent().removeClass("open"),n=angular.noop,t=null},e.bind("click",n))})}}}]),angular.module("ui.bootstrap.modal",["ui.bootstrap.dialog"]).directive("modal",["$parse","$dialog",function(e,t){return{restrict:"EA",terminal:!0,link:function(n,a,i){var o,r=angular.extend({},n.$eval(i.uiOptions||i.bsOptions||i.options)),l=i.modal||i.show;r=angular.extend(r,{template:a.html(),resolve:{$scope:function(){return n}}});var s=t.dialog(r);a.remove(),o=i.close?function(){e(i.close)(n)}:function(){angular.isFunction(e(l).assign)&&e(l).assign(n,!1)},n.$watch(l,function(e){e?s.open().then(function(){o()}):s.isOpen()&&s.close()})}}}]),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$interpolate",function(e,t){this.currentPage=1,this.noPrevious=function(){return 1===this.currentPage},this.noNext=function(){return this.currentPage===e.numPages},this.isActive=function(e){return this.currentPage===e},this.reset=function(){e.pages=[],this.currentPage=parseInt(e.currentPage,10),this.currentPage>e.numPages&&e.selectPage(e.numPages)};var n=this;e.selectPage=function(t){!n.isActive(t)&&t>0&&e.numPages>=t&&(e.currentPage=t,e.onSelectPage({page:t}))},this.getAttributeValue=function(n,a,i){return angular.isDefined(n)?i?t(n)(e.$parent):e.$parent.$eval(n):a}}]).constant("paginationConfig",{boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["paginationConfig",function(e){return{restrict:"EA",scope:{numPages:"=",currentPage:"=",maxSize:"=",onSelectPage:"&"},controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(t,n,a,i){function o(e,t,n,a){return{number:e,text:t,active:n,disabled:a}}var r=i.getAttributeValue(a.boundaryLinks,e.boundaryLinks),l=i.getAttributeValue(a.directionLinks,e.directionLinks),s=i.getAttributeValue(a.firstText,e.firstText,!0),c=i.getAttributeValue(a.previousText,e.previousText,!0),u=i.getAttributeValue(a.nextText,e.nextText,!0),p=i.getAttributeValue(a.lastText,e.lastText,!0),d=i.getAttributeValue(a.rotate,e.rotate);t.$watch("numPages + currentPage + maxSize",function(){i.reset();var e=1,n=t.numPages,a=angular.isDefined(t.maxSize)&&t.maxSizet.numPages&&(n=t.numPages,e=n-t.maxSize+1)):(e=(Math.ceil(i.currentPage/t.maxSize)-1)*t.maxSize+1,n=Math.min(e+t.maxSize-1,t.numPages)));for(var m=e;n>=m;m++){var g=o(m,m,i.isActive(m),!1);t.pages.push(g)}if(a&&!d){if(e>1){var f=o(e-1,"...",!1,!1);t.pages.unshift(f)}if(t.numPages>n){var h=o(n+1,"...",!1,!1);t.pages.push(h)}}if(l){var v=o(i.currentPage-1,c,!1,i.noPrevious());t.pages.unshift(v);var b=o(i.currentPage+1,u,!1,i.noNext());t.pages.push(b)}if(r){var $=o(1,s,!1,i.noPrevious());t.pages.unshift($);var y=o(t.numPages,p,!1,i.noNext());t.pages.push(y)}})}}}]).constant("pagerConfig",{previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(e){return{restrict:"EA",scope:{numPages:"=",currentPage:"=",onSelectPage:"&"},controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(t,n,a,i){function o(e,t,n,a,i){return{number:e,text:t,disabled:n,previous:s&&a,next:s&&i}}var r=i.getAttributeValue(a.previousText,e.previousText,!0),l=i.getAttributeValue(a.nextText,e.nextText,!0),s=i.getAttributeValue(a.align,e.align);t.$watch("numPages + currentPage",function(){i.reset();var e=o(i.currentPage-1,r,i.noPrevious(),!0,!1);t.pages.unshift(e);var n=o(i.currentPage+1,l,i.noNext(),!1,!0);t.pages.push(n)})}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position"]).provider("$tooltip",function(){function e(e){var t=/[A-Z]/g,n="-";return e.replace(t,function(e,t){return(t?n:"")+e.toLowerCase()})}var t={placement:"top",animation:!0,popupDelay:0},n={mouseenter:"mouseleave",click:"click",focus:"blur"},a={};this.options=function(e){angular.extend(a,e)},this.setTriggers=function(e){angular.extend(n,e)},this.$get=["$window","$compile","$timeout","$parse","$document","$position","$interpolate",function(i,o,r,l,s,c,u){return function(i,p,d){function m(e){var t=e||g.trigger||d,a=n[t]||t;return{show:t,hide:a}}var g=angular.extend({},t,a),f=e(i),h=u.startSymbol(),v=u.endSymbol(),b="<"+f+"-popup "+'title="'+h+"tt_title"+v+'" '+'content="'+h+"tt_content"+v+'" '+'placement="'+h+"tt_placement"+v+'" '+'animation="tt_animation()" '+'is-open="tt_isOpen"'+">"+"";return{restrict:"EA",scope:!0,link:function(e,t,n){function a(){e.tt_isOpen?d():u()}function u(){e.tt_popupDelay?$=r(f,e.tt_popupDelay):e.$apply(f)}function d(){e.$apply(function(){h()})}function f(){var n,a,i,o;if(e.tt_content){switch(v&&r.cancel(v),w.css({top:0,left:0,display:"block"}),k?(y=y||s.find("body"),y.append(w)):t.after(w),n=k?c.offset(t):c.position(t),a=w.prop("offsetWidth"),i=w.prop("offsetHeight"),e.tt_placement){case"mouse":var l=c.mouse();o={top:l.y,left:l.x};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width};break;case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-a/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-a};break;default:o={top:n.top-i,left:n.left+n.width/2-a/2}}o.top+="px",o.left+="px",w.css(o),e.tt_isOpen=!0}}function h(){e.tt_isOpen=!1,r.cancel($),angular.isDefined(e.tt_animation)&&e.tt_animation()?v=r(function(){w.remove()},500):w.remove()}var v,$,y,w=o(b)(e),k=angular.isDefined(g.appendToBody)?g.appendToBody:!1,D=m(void 0),x=!1;e.tt_isOpen=!1,n.$observe(i,function(t){e.tt_content=t}),n.$observe(p+"Title",function(t){e.tt_title=t}),n.$observe(p+"Placement",function(t){e.tt_placement=angular.isDefined(t)?t:g.placement}),n.$observe(p+"Animation",function(t){e.tt_animation=angular.isDefined(t)?l(t):function(){return g.animation}}),n.$observe(p+"PopupDelay",function(t){var n=parseInt(t,10);e.tt_popupDelay=isNaN(n)?g.popupDelay:n}),n.$observe(p+"Trigger",function(e){x&&(t.unbind(D.show,u),t.unbind(D.hide,d)),D=m(e),D.show===D.hide?t.bind(D.show,a):(t.bind(D.show,u),t.bind(D.hide,d)),x=!0}),n.$observe(p+"AppendToBody",function(t){k=angular.isDefined(t)?l(t)(e):k}),k&&e.$on("$locationChangeSuccess",function(){e.tt_isOpen&&h()}),e.$on("$destroy",function(){e.tt_isOpen?h():w.remove()})}}}}]}).directive("tooltipPopup",function(){return{restrict:"E",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(e){return e("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"E",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(e){return e("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$compile","$timeout","$parse","$window","$tooltip",function(e,t,n,a,i){return i("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",["ui.bootstrap.transition"]).constant("progressConfig",{animate:!0,autoType:!1,stackedTypes:["success","info","warning","danger"]}).controller("ProgressBarController",["$scope","$attrs","progressConfig",function(e,t,n){function a(e){return r[e]}var i=angular.isDefined(t.animate)?e.$eval(t.animate):n.animate,o=angular.isDefined(t.autoType)?e.$eval(t.autoType):n.autoType,r=angular.isDefined(t.stackedTypes)?e.$eval("["+t.stackedTypes+"]"):n.stackedTypes;this.makeBar=function(e,t,n){var r=angular.isObject(e)?e.value:e||0,l=angular.isObject(t)?t.value:t||0,s=angular.isObject(e)&&angular.isDefined(e.type)?e.type:o?a(n||0):null;return{from:l,to:r,type:s,animate:i}},this.addBar=function(t){e.bars.push(t),e.totalPercent+=t.to},this.clearBars=function(){e.bars=[],e.totalPercent=0},this.clearBars()}]).directive("progress",function(){return{restrict:"EA",replace:!0,controller:"ProgressBarController",scope:{value:"=percent",onFull:"&",onEmpty:"&"},templateUrl:"template/progressbar/progress.html",link:function(e,t,n,a){e.$watch("value",function(e,t){if(a.clearBars(),angular.isArray(e))for(var n=0,i=e.length;i>n;n++)a.addBar(a.makeBar(e[n],t[n],n));else a.addBar(a.makeBar(e,t))},!0),e.$watch("totalPercent",function(t){t>=100?e.onFull():0>=t&&e.onEmpty()},!0)}}}).directive("progressbar",["$transition",function(e){return{restrict:"EA",replace:!0,scope:{width:"=",old:"=",type:"=",animate:"="},templateUrl:"template/progressbar/bar.html",link:function(t,n){t.$watch("width",function(a){t.animate?(n.css("width",t.old+"%"),e(n,{width:a+"%"})):n.css("width",a+"%")})}}}]),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5}).directive("rating",["ratingConfig","$parse",function(e,t){return{restrict:"EA",scope:{value:"=",onHover:"&",onLeave:"&"},templateUrl:"template/rating/rating.html",replace:!0,link:function(n,a,i){var o=angular.isDefined(i.max)?n.$parent.$eval(i.max):e.max;n.range=[];for(var r=1;o>=r;r++)n.range.push(r);n.rate=function(e){n.readonly||(n.value=e)},n.enter=function(e){n.readonly||(n.val=e),n.onHover({value:e})},n.reset=function(){n.val=angular.copy(n.value),n.onLeave()},n.reset(),n.$watch("value",function(e){n.val=e}),n.readonly=!1,i.readonly&&n.$parent.$watch(t(i.readonly),function(e){n.readonly=!!e})}}}]),angular.module("ui.bootstrap.tabs",[]).directive("tabs",function(){return function(){throw Error("The `tabs` directive is deprecated, please migrate to `tabset`. Instructions can be found at http://github.com/angular-ui/bootstrap/tree/master/CHANGELOG.md")}}).controller("TabsetController",["$scope","$element",function(e){var t=this,n=t.tabs=e.tabs=[];t.select=function(e){angular.forEach(n,function(e){e.active=!1}),e.active=!0},t.addTab=function(e){n.push(e),(1===n.length||e.active)&&t.select(e)},t.removeTab=function(e){var a=n.indexOf(e);if(e.active&&n.length>1){var i=a==n.length-1?a-1:a+1;t.select(n[i])}n.splice(a,1)}}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,require:"^tabset",scope:{},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",compile:function(e,t,n){return function(e,t,a,i){e.vertical=angular.isDefined(a.vertical)?e.$eval(a.vertical):!1,e.type=angular.isDefined(a.type)?e.$parent.$eval(a.type):"tabs",e.direction=angular.isDefined(a.direction)?e.$parent.$eval(a.direction):"top",e.tabsAbove="below"!=e.direction,i.$scope=e,i.$transcludeFn=n}}}}).directive("tab",["$parse","$http","$templateCache","$compile",function(e){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(t,n,a){return function(t,n,i,o){var r,l;i.active?(r=e(i.active),l=r.assign,t.$parent.$watch(r,function(e){t.active=!!e}),t.active=r(t.$parent)):l=r=angular.noop,t.$watch("active",function(e){l(t.$parent,e),e?(o.select(t),t.onSelect()):t.onDeselect()}),t.disabled=!1,i.disabled&&t.$parent.$watch(e(i.disabled),function(e){t.disabled=!!e -}),t.select=function(){t.disabled||(t.active=!0)},o.addTab(t),t.$on("$destroy",function(){o.removeTab(t)}),t.active&&l(t.$parent,!0),t.$transcludeFn=a}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(e,t){e.$watch("headingElement",function(e){e&&(t.html(""),t.append(e))})}}}]).directive("tabContentTransclude",["$compile","$parse",function(){function e(e){return e.tagName&&(e.hasAttribute("tab-heading")||e.hasAttribute("data-tab-heading")||"tab-heading"===e.tagName.toLowerCase()||"data-tab-heading"===e.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(t,n,a){var i=t.$eval(a.tabContentTransclude);i.$transcludeFn(i.$parent,function(t){angular.forEach(t,function(t){e(t)?i.headingElement=t:n.append(t)})})}}}]).directive("tabsetTitles",function(){return{restrict:"A",require:"^tabset",templateUrl:"template/tabs/tabset-titles.html",replace:!0,link:function(e,t,n,a){e.$eval(n.tabsetTitles)?a.$transcludeFn(a.$scope.$parent,function(e){t.append(e)}):t.remove()}}}),angular.module("ui.bootstrap.timepicker",[]).filter("pad",function(){return function(e){return angular.isDefined(e)&&2>(""+e).length&&(e="0"+e),e}}).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:["AM","PM"],readonlyInput:!1,mousewheel:!0}).directive("timepicker",["padFilter","$parse","timepickerConfig",function(e,t,n){return{restrict:"EA",require:"ngModel",replace:!0,templateUrl:"template/timepicker/timepicker.html",scope:{model:"=ngModel"},link:function(a,i,o){function r(){var e=parseInt(a.hours,10),t=a.showMeridian?e>0&&13>e:e>=0&&24>e;return t?(a.showMeridian&&(12===e&&(e=0),a.meridian===u[1]&&(e+=12)),e):void 0}function l(){var t=c.getHours();a.showMeridian&&(t=0===t||12===t?12:t%12),a.hours="h"===b?t:e(t),a.validHours=!0;var n=c.getMinutes();a.minutes="m"===b?n:e(n),a.validMinutes=!0,a.meridian=a.showMeridian?12>c.getHours()?u[0]:u[1]:"",b=!1}function s(e){var t=new Date(c.getTime()+6e4*e);c.setHours(t.getHours()),c.setMinutes(t.getMinutes()),a.model=new Date(c)}var c=new Date,u=n.meridians,p=n.hourStep;o.hourStep&&a.$parent.$watch(t(o.hourStep),function(e){p=parseInt(e,10)});var d=n.minuteStep;o.minuteStep&&a.$parent.$watch(t(o.minuteStep),function(e){d=parseInt(e,10)}),a.showMeridian=n.showMeridian,o.showMeridian&&a.$parent.$watch(t(o.showMeridian),function(e){if(a.showMeridian=!!e,a.model)l();else{var t=new Date(c),n=r();angular.isDefined(n)&&t.setHours(n),a.model=new Date(t)}});var m=i.find("input"),g=m.eq(0),f=m.eq(1),h=angular.isDefined(o.mousewheel)?a.$eval(o.mousewheel):n.mousewheel;if(h){var v=function(e){e.originalEvent&&(e=e.originalEvent);var t=e.wheelDelta?e.wheelDelta:-e.deltaY;return e.detail||t>0};g.bind("mousewheel wheel",function(e){a.$apply(v(e)?a.incrementHours():a.decrementHours()),e.preventDefault()}),f.bind("mousewheel wheel",function(e){a.$apply(v(e)?a.incrementMinutes():a.decrementMinutes()),e.preventDefault()})}var b=!1;a.readonlyInput=angular.isDefined(o.readonlyInput)?a.$eval(o.readonlyInput):n.readonlyInput,a.readonlyInput?(a.updateHours=angular.noop,a.updateMinutes=angular.noop):(a.updateHours=function(){var e=r();angular.isDefined(e)?(b="h",null===a.model&&(a.model=new Date(c)),a.model.setHours(e)):(a.model=null,a.validHours=!1)},g.bind("blur",function(){a.validHours&&10>a.hours&&a.$apply(function(){a.hours=e(a.hours)})}),a.updateMinutes=function(){var e=parseInt(a.minutes,10);e>=0&&60>e?(b="m",null===a.model&&(a.model=new Date(c)),a.model.setMinutes(e)):(a.model=null,a.validMinutes=!1)},f.bind("blur",function(){a.validMinutes&&10>a.minutes&&a.$apply(function(){a.minutes=e(a.minutes)})})),a.$watch(function(){return+a.model},function(e){!isNaN(e)&&e>0&&(c=new Date(e),l())}),a.incrementHours=function(){s(60*p)},a.decrementHours=function(){s(60*-p)},a.incrementMinutes=function(){s(d)},a.decrementMinutes=function(){s(-d)},a.toggleMeridian=function(){s(720*(12>c.getHours()?1:-1))}}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position"]).factory("typeaheadParser",["$parse",function(e){var t=/^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;return{parse:function(n){var a=n.match(t);if(!a)throw Error("Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_' but got '"+n+"'.");return{itemName:a[3],source:e(a[4]),viewMapper:e(a[2]||a[1]),modelMapper:e(a[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(e,t,n,a,i,o,r){var l=[9,13,27,38,40];return{require:"ngModel",link:function(s,c,u,p){var d=s.$eval(u.typeaheadMinLength)||1,m=s.$eval(u.typeaheadWaitMs)||0,g=s.$eval(u.typeaheadEditable)!==!1,f=t(u.typeaheadLoading).assign||angular.noop,h=t(u.typeaheadOnSelect),v=u.typeaheadInputFormatter?t(u.typeaheadInputFormatter):void 0,b=t(u.ngModel).assign,$=r.parse(u.typeahead),y=angular.element("");y.attr({matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(u.typeaheadTemplateUrl)&&y.attr("template-url",u.typeaheadTemplateUrl);var w=s.$new();s.$on("$destroy",function(){w.$destroy()});var k=function(){w.matches=[],w.activeIdx=-1},D=function(e){var t={$viewValue:e};f(s,!0),n.when($.source(w,t)).then(function(n){if(e===p.$viewValue){if(n.length>0){w.activeIdx=0,w.matches.length=0;for(var a=0;n.length>a;a++)t[$.itemName]=n[a],w.matches.push({label:$.viewMapper(w,t),model:n[a]});w.query=e,w.position=o.position(c),w.position.top=w.position.top+c.prop("offsetHeight")}else k();f(s,!1)}},function(){k(),f(s,!1)})};k(),w.query=void 0;var x;p.$parsers.push(function(e){return k(),e&&e.length>=d&&(m>0?(x&&a.cancel(x),x=a(function(){D(e)},m)):D(e)),g?e:void 0}),p.$formatters.push(function(e){var t,n,a={};return v?(a.$model=e,v(s,a)):(a[$.itemName]=e,t=$.viewMapper(s,a),n=$.viewMapper(s,{}),t!==n?t:e)}),w.select=function(e){var t,n,a={};a[$.itemName]=n=w.matches[e].model,t=$.modelMapper(s,a),b(s,t),h(s,{$item:n,$model:t,$label:$.viewMapper(s,a)}),k(),c[0].focus()},c.bind("keydown",function(e){0!==w.matches.length&&-1!==l.indexOf(e.which)&&(e.preventDefault(),40===e.which?(w.activeIdx=(w.activeIdx+1)%w.matches.length,w.$digest()):38===e.which?(w.activeIdx=(w.activeIdx?w.activeIdx:w.matches.length)-1,w.$digest()):13===e.which||9===e.which?w.$apply(function(){w.select(w.activeIdx)}):27===e.which&&(e.stopPropagation(),k(),w.$digest()))}),i.bind("click",function(){k(),w.$digest()}),c.after(e(y)(w))}}}]).directive("typeaheadPopup",function(){return{restrict:"E",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(e,t,n){e.templateUrl=n.templateUrl,e.isOpen=function(){return e.matches.length>0},e.isActive=function(t){return e.active==t},e.selectActive=function(t){e.active=t},e.selectMatch=function(t){e.select({activeIdx:t})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(e,t,n,a){return{restrict:"E",scope:{index:"=",match:"=",query:"="},link:function(i,o,r){var l=a(r.templateUrl)(i.$parent)||"template/typeahead/typeahead-match.html";e.get(l,{cache:t}).success(function(e){o.replaceWith(n(e.trim())(i))})}}}]).filter("typeaheadHighlight",function(){function e(e){return e.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(t,n){return n?t.replace(RegExp(e(n),"gi"),"$&"):n}}),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(e){e.put("template/accordion/accordion-group.html",'
\n \n
\n
\n
')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(e){e.put("template/accordion/accordion.html",'
')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(e){e.put("template/alert/alert.html","
\n \n
\n
\n")}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(e){e.put("template/carousel/carousel.html",'\n')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(e){e.put("template/carousel/slide.html","
\n")}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(e){e.put("template/datepicker/datepicker.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
#{{label}}
{{ getWeekNumber(row) }}\n \n
\n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(e){e.put("template/datepicker/popup.html",'')}]),angular.module("template/dialog/message.html",[]).run(["$templateCache",function(e){e.put("template/dialog/message.html",'\n\n\n')}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(e){e.put("template/modal/backdrop.html",'')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(e){e.put("template/modal/window.html",'')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(e){e.put("template/pagination/pager.html",'
\n \n
\n')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(e){e.put("template/pagination/pagination.html",'\n')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(e){e.put("template/tooltip/tooltip-html-unsafe-popup.html",'
\n
\n
\n
\n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(e){e.put("template/tooltip/tooltip-popup.html",'
\n
\n
\n
\n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(e){e.put("template/popover/popover.html",'
\n
\n\n
\n

\n
\n
\n
\n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(e){e.put("template/progressbar/bar.html",'
')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(e){e.put("template/progressbar/progress.html",'
')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(e){e.put("template/rating/rating.html",'\n \n')}]),angular.module("template/tabs/pane.html",[]).run(["$templateCache",function(e){e.put("template/tabs/pane.html",'
\n')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(e){e.put("template/tabs/tab.html",'
  • \n {{heading}}\n
  • \n')}]),angular.module("template/tabs/tabs.html",[]).run(["$templateCache",function(e){e.put("template/tabs/tabs.html",'
    \n \n
    \n
    \n')}]),angular.module("template/tabs/tabset-titles.html",[]).run(["$templateCache",function(e){e.put("template/tabs/tabset-titles.html","
      \n
    \n")}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(e){e.put("template/tabs/tabset.html",'\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(e){e.put("template/timepicker/timepicker.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
     
    :
     
    ')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(e){e.put("template/typeahead/typeahead-match.html",'')}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(e){e.put("template/typeahead/typeahead-popup.html",'')}]),angular.module("template/typeahead/typeahead.html",[]).run(["$templateCache",function(e){e.put("template/typeahead/typeahead.html",'')}]); \ No newline at end of file +angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdownToggle","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"]),angular.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/popup.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset-titles.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(e,t,n){function a(e){for(var t in e)if(void 0!==r.style[t])return e[t]}var i=function(a,r,o){o=o||{};var l=e.defer(),s=i[o.animation?"animationEndEventName":"transitionEndEventName"],c=function(){n.$apply(function(){a.unbind(s,c),l.resolve(a)})};return s&&a.bind(s,c),t(function(){angular.isString(r)?a.addClass(r):angular.isFunction(r)?r(a):angular.isObject(r)&&a.css(r),s||l.resolve(a)}),l.promise.cancel=function(){s&&a.unbind(s,c),l.reject("Transition cancelled")},l.promise},r=document.createElement("trans"),o={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},l={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return i.transitionEndEventName=a(o),i.animationEndEventName=a(l),i}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(e){var t=function(e,t,n){t.removeClass("collapse"),t.css({height:n}),t[0].offsetWidth,t.addClass("collapse")};return{link:function(n,a,i){var r,o=!0;n.$watch(function(){return a[0].scrollHeight},function(){0!==a[0].scrollHeight&&(r||(o?t(n,a,a[0].scrollHeight+"px"):t(n,a,"auto")))}),n.$watch(i.collapse,function(e){e?u():c()});var l,s=function(t){return l&&l.cancel(),l=e(a,t),l.then(function(){l=void 0},function(){l=void 0}),l},c=function(){o?(o=!1,r||t(n,a,"auto")):s({height:a[0].scrollHeight+"px"}).then(function(){r||t(n,a,"auto")}),r=!1},u=function(){r=!0,o?(o=!1,t(n,a,0)):(t(n,a,a[0].scrollHeight+"px"),s({height:"0"}))}}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(e,t,n){this.groups=[],this.closeOthers=function(a){var i=angular.isDefined(t.closeOthers)?e.$eval(t.closeOthers):n.closeOthers;i&&angular.forEach(this.groups,function(e){e!==a&&(e.isOpen=!1)})},this.addGroup=function(e){var t=this;this.groups.push(e),e.$on("$destroy",function(){t.removeGroup(e)})},this.removeGroup=function(e){var t=this.groups.indexOf(e);-1!==t&&this.groups.splice(this.groups.indexOf(e),1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",["$parse","$transition","$timeout",function(e){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@"},controller:["$scope",function(){this.setHeading=function(e){this.heading=e}}],link:function(t,n,a,i){var r,o;i.addGroup(t),t.isOpen=!1,a.isOpen&&(r=e(a.isOpen),o=r.assign,t.$watch(function(){return r(t.$parent)},function(e){t.isOpen=e}),t.isOpen=r?r(t.$parent):!1),t.$watch("isOpen",function(e){e&&i.closeOthers(t),o&&o(t.$parent,e)})}}}]).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",compile:function(e,t,n){return function(e,t,a,i){i.setHeading(n(e,function(){}))}}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(e,t,n,a){e.$watch(function(){return a[n.accordionTransclude]},function(e){e&&(t.html(""),t.append(e))})}}}),angular.module("ui.bootstrap.alert",[]).directive("alert",function(){return{restrict:"EA",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"=",close:"&"},link:function(e,t,n){e.closeable="close"in n}}}),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(e,t,n){t.addClass("ng-binding").data("$binding",n.bindHtmlUnsafe),e.$watch(n.bindHtmlUnsafe,function(e){t.html(e||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).directive("btnRadio",["buttonConfig",function(e){var t=e.activeClass||"active",n=e.toggleEvent||"click";return{require:"ngModel",link:function(e,a,i,r){r.$render=function(){a.toggleClass(t,angular.equals(r.$modelValue,e.$eval(i.btnRadio)))},a.bind(n,function(){a.hasClass(t)||e.$apply(function(){r.$setViewValue(e.$eval(i.btnRadio)),r.$render()})})}}}]).directive("btnCheckbox",["buttonConfig",function(e){var t=e.activeClass||"active",n=e.toggleEvent||"click";return{require:"ngModel",link:function(e,a,i,r){function o(){var t=e.$eval(i.btnCheckboxTrue);return angular.isDefined(t)?t:!0}function l(){var t=e.$eval(i.btnCheckboxFalse);return angular.isDefined(t)?t:!1}r.$render=function(){a.toggleClass(t,angular.equals(r.$modelValue,o()))},a.bind(n,function(){e.$apply(function(){r.$setViewValue(a.hasClass(t)?l():o()),r.$render()})})}}}]),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$transition","$q",function(e,t,n){function a(){function n(){r?(e.next(),a()):e.pause()}i&&t.cancel(i);var o=+e.interval;!isNaN(o)&&o>=0&&(i=t(n,o))}var i,r,o=this,l=o.slides=[],s=-1;o.currentSlide=null,o.select=function(i,r){function c(){o.currentSlide&&angular.isString(r)&&!e.noTransition&&i.$element?(i.$element.addClass(r),i.$element[0].offsetWidth,angular.forEach(l,function(e){angular.extend(e,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(i,{direction:r,active:!0,entering:!0}),angular.extend(o.currentSlide||{},{direction:r,leaving:!0}),e.$currentTransition=n(i.$element,{}),function(t,n){e.$currentTransition.then(function(){u(t,n)},function(){u(t,n)})}(i,o.currentSlide)):u(i,o.currentSlide),o.currentSlide=i,s=p,a()}function u(t,n){angular.extend(t,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(n||{},{direction:"",active:!1,leaving:!1,entering:!1}),e.$currentTransition=null}var p=l.indexOf(i);void 0===r&&(r=p>s?"next":"prev"),i&&i!==o.currentSlide&&(e.$currentTransition?(e.$currentTransition.cancel(),t(c)):c())},o.indexOfSlide=function(e){return l.indexOf(e)},e.next=function(){var t=(s+1)%l.length;return e.$currentTransition?void 0:o.select(l[t],"next")},e.prev=function(){var t=0>s-1?l.length-1:s-1;return e.$currentTransition?void 0:o.select(l[t],"prev")},e.select=function(e){o.select(e)},e.isActive=function(e){return o.currentSlide===e},e.slides=function(){return l},e.$watch("interval",a),e.play=function(){r||(r=!0,a())},e.pause=function(){e.noPause||(r=!1,i&&t.cancel(i))},o.addSlide=function(t,n){t.$element=n,l.push(t),1===l.length||t.active?(o.select(l[l.length-1]),1==l.length&&e.play()):t.active=!1},o.removeSlide=function(e){var t=l.indexOf(e);l.splice(t,1),l.length>0&&e.active?t>=l.length?o.select(l[t-1]):o.select(l[t]):s>t&&s--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",["$parse",function(e){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{},link:function(t,n,a,i){if(a.active){var r=e(a.active),o=r.assign,l=t.active=r(t.$parent);t.$watch(function(){var e=r(t.$parent);return e!==t.active&&(e!==l?l=t.active=e:o(t.$parent,e=l=t.active)),e})}i.addSlide(t,n),t.$on("$destroy",function(){i.removeSlide(t)}),t.$watch("active",function(e){e&&i.select(t)})}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(e,t){function n(e,n){return e.currentStyle?e.currentStyle[n]:t.getComputedStyle?t.getComputedStyle(e)[n]:e.style[n]}function a(e){return"static"===(n(e,"position")||"static")}var i=function(t){for(var n=e[0],i=t.offsetParent||n;i&&i!==n&&a(i);)i=i.offsetParent;return i||n};return{position:function(t){var n=this.offset(t),a={top:0,left:0},r=i(t[0]);return r!=e[0]&&(a=this.offset(angular.element(r)),a.top+=r.clientTop-r.scrollTop,a.left+=r.clientLeft-r.scrollLeft),{width:t.prop("offsetWidth"),height:t.prop("offsetHeight"),top:n.top-a.top,left:n.left-a.left}},offset:function(n){var a=n[0].getBoundingClientRect();return{width:n.prop("offsetWidth"),height:n.prop("offsetHeight"),top:a.top+(t.pageYOffset||e[0].body.scrollTop||e[0].documentElement.scrollTop),left:a.left+(t.pageXOffset||e[0].body.scrollLeft||e[0].documentElement.scrollLeft)}}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.position"]).constant("datepickerConfig",{dayFormat:"dd",monthFormat:"MMMM",yearFormat:"yyyy",dayHeaderFormat:"EEE",dayTitleFormat:"MMMM yyyy",monthTitleFormat:"yyyy",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","dateFilter","datepickerConfig",function(e,t,n,a){function i(t,n){return angular.isDefined(t)?e.$parent.$eval(t):n}function r(e,t){return new Date(e,t,0).getDate()}function o(e,t){for(var n=Array(t),a=e,i=0;t>i;)n[i++]=new Date(a),a.setDate(a.getDate()+1);return n}function l(e,t,a,i){return{date:e,label:n(e,t),selected:!!a,secondary:!!i}}var s={day:i(t.dayFormat,a.dayFormat),month:i(t.monthFormat,a.monthFormat),year:i(t.yearFormat,a.yearFormat),dayHeader:i(t.dayHeaderFormat,a.dayHeaderFormat),dayTitle:i(t.dayTitleFormat,a.dayTitleFormat),monthTitle:i(t.monthTitleFormat,a.monthTitleFormat)},c=i(t.startingDay,a.startingDay),u=i(t.yearRange,a.yearRange);this.minDate=a.minDate?new Date(a.minDate):null,this.maxDate=a.maxDate?new Date(a.maxDate):null,this.modes=[{name:"day",getVisibleDates:function(e,t){var a=e.getFullYear(),i=e.getMonth(),u=new Date(a,i,1),p=c-u.getDay(),d=p>0?7-p:-p,f=new Date(u),m=0;d>0&&(f.setDate(-d+1),m+=d),m+=r(a,i+1),m+=(7-m%7)%7;for(var g=o(f,m),h=Array(7),v=0;m>v;v++){var b=new Date(g[v]);g[v]=l(b,s.day,t&&t.getDate()===b.getDate()&&t.getMonth()===b.getMonth()&&t.getFullYear()===b.getFullYear(),b.getMonth()!==i)}for(var $=0;7>$;$++)h[$]=n(g[$].date,s.dayHeader);return{objects:g,title:n(e,s.dayTitle),labels:h}},compare:function(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate())-new Date(t.getFullYear(),t.getMonth(),t.getDate())},split:7,step:{months:1}},{name:"month",getVisibleDates:function(e,t){for(var a=Array(12),i=e.getFullYear(),r=0;12>r;r++){var o=new Date(i,r,1);a[r]=l(o,s.month,t&&t.getMonth()===r&&t.getFullYear()===i)}return{objects:a,title:n(e,s.monthTitle)}},compare:function(e,t){return new Date(e.getFullYear(),e.getMonth())-new Date(t.getFullYear(),t.getMonth())},split:3,step:{years:1}},{name:"year",getVisibleDates:function(e,t){for(var n=Array(u),a=e.getFullYear(),i=parseInt((a-1)/u,10)*u+1,r=0;u>r;r++){var o=new Date(i+r,0,1);n[r]=l(o,s.year,t&&t.getFullYear()===o.getFullYear())}return{objects:n,title:[n[0].label,n[u-1].label].join(" - ")}},compare:function(e,t){return e.getFullYear()-t.getFullYear()},split:5,step:{years:u}}],this.isDisabled=function(t,n){var a=this.modes[n||0];return this.minDate&&0>a.compare(t,this.minDate)||this.maxDate&&a.compare(t,this.maxDate)>0||e.dateDisabled&&e.dateDisabled({date:t,mode:a.name})}}]).directive("datepicker",["dateFilter","$parse","datepickerConfig","$log",function(e,t,n,a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(e,i,r,o){function l(){e.showWeekNumbers=0===m&&h}function s(e,t){for(var n=[];e.length>0;)n.push(e.splice(0,t));return n}function c(t){var n=null,i=!0;f.$modelValue&&(n=new Date(f.$modelValue),isNaN(n)?(i=!1,a.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.')):t&&(g=n)),f.$setValidity("date",i);var r=d.modes[m],o=r.getVisibleDates(g,n);angular.forEach(o.objects,function(e){e.disabled=d.isDisabled(e.date,m)}),f.$setValidity("date-disabled",!n||!d.isDisabled(n)),e.rows=s(o.objects,r.split),e.labels=o.labels||[],e.title=o.title}function u(e){m=e,l(),c()}function p(e){var t=new Date(e);t.setDate(t.getDate()+4-(t.getDay()||7));var n=t.getTime();return t.setMonth(0),t.setDate(1),Math.floor(Math.round((n-t)/864e5)/7)+1}var d=o[0],f=o[1];if(f){var m=0,g=new Date,h=n.showWeeks;r.showWeeks?e.$parent.$watch(t(r.showWeeks),function(e){h=!!e,l()}):l(),r.min&&e.$parent.$watch(t(r.min),function(e){d.minDate=e?new Date(e):null,c()}),r.max&&e.$parent.$watch(t(r.max),function(e){d.maxDate=e?new Date(e):null,c()}),f.$render=function(){c(!0)},e.select=function(e){if(0===m){var t=new Date(f.$modelValue);t.setFullYear(e.getFullYear(),e.getMonth(),e.getDate()),f.$setViewValue(t),c(!0)}else g=e,u(m-1)},e.move=function(e){var t=d.modes[m].step;g.setMonth(g.getMonth()+e*(t.months||0)),g.setFullYear(g.getFullYear()+e*(t.years||0)),c()},e.toggleMode=function(){u((m+1)%d.modes.length)},e.getWeekNumber=function(t){return 0===m&&e.showWeekNumbers&&7===t.length?p(t[0].date):null}}}}}]).constant("datepickerPopupConfig",{dateFormat:"yyyy-MM-dd",closeOnDateSelection:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","datepickerPopupConfig",function(e,t,n,a,i,r){return{restrict:"EA",require:"ngModel",link:function(o,l,s,c){function u(e){$?$(o,!!e):v.isOpen=!!e}function p(e){if(e){if(angular.isDate(e))return c.$setValidity("date",!0),e;if(angular.isString(e)){var t=new Date(e);return isNaN(t)?(c.$setValidity("date",!1),void 0):(c.$setValidity("date",!0),t)}return c.$setValidity("date",!1),void 0}return c.$setValidity("date",!0),null}function d(){v.date=c.$modelValue,m()}function f(e,n,a){e&&(o.$watch(t(e),function(e){v[n]=e}),D.attr(a||n,n))}function m(){v.position=a.position(l),v.position.top=v.position.top+l.prop("offsetHeight")}var g=angular.isDefined(s.closeOnDateSelection)?v.$eval(s.closeOnDateSelection):r.closeOnDateSelection,h=s.datepickerPopup||r.dateFormat,v=o.$new();o.$on("$destroy",function(){v.$destroy()});var b,$;s.isOpen&&(b=t(s.isOpen),$=b.assign,o.$watch(b,function(e){v.isOpen=!!e})),v.isOpen=b?b(o):!1;var y=function(e){v.isOpen&&e.target!==l[0]&&v.$apply(function(){u(!1)})},w=function(){v.$apply(function(){u(!0)})},k=angular.element("");k.attr({"ng-model":"date","ng-change":"dateSelection()"});var D=k.find("datepicker");s.datepickerOptions&&D.attr(angular.extend({},o.$eval(s.datepickerOptions))),c.$parsers.unshift(p),v.dateSelection=function(){c.$setViewValue(v.date),c.$render(),g&&u(!1)},l.bind("input change keyup",function(){v.$apply(function(){d()})}),c.$render=function(){var e=c.$viewValue?i(c.$viewValue,h):"";l.val(e),d()},f(s.min,"min"),f(s.max,"max"),s.showWeeks?f(s.showWeeks,"showWeeks","show-weeks"):(v.showWeeks=!0,D.attr("show-weeks","showWeeks")),s.dateDisabled&&D.attr("date-disabled",s.dateDisabled);var x=!1,T=!1;v.$watch("isOpen",function(e){e?(m(),n.bind("click",y),T&&l.unbind("focus",w),l[0].focus(),x=!0):(x&&n.unbind("click",y),l.bind("focus",w),T=!0),$&&$(o,e)});var C=t(s.ngModel).assign;v.today=function(){C(o,new Date)},v.clear=function(){C(o,null)},l.after(e(k)(v))}}}]).directive("datepickerPopupWrap",[function(){return{restrict:"E",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(e,t){t.bind("click",function(e){e.preventDefault(),e.stopPropagation()})}}}]),angular.module("ui.bootstrap.dropdownToggle",[]).directive("dropdownToggle",["$document","$location",function(e){var t=null,n=angular.noop;return{restrict:"CA",link:function(a,i){a.$watch("$location.path",function(){n()}),i.parent().bind("click",function(){n()}),i.bind("click",function(a){var r=i===t;a.preventDefault(),a.stopPropagation(),t&&n(),r||(i.parent().addClass("open"),t=i,n=function(a){a&&(a.preventDefault(),a.stopPropagation()),e.unbind("click",n),i.parent().removeClass("open"),n=angular.noop,t=null},e.bind("click",n))})}}}]),angular.module("ui.bootstrap.modal",[]).factory("$$stackedMap",function(){return{createNew:function(){var e=[];return{add:function(t,n){e.push({key:t,value:n})},get:function(t){for(var n=0;e.length>n;n++)if(t==e[n].key)return e[n]},keys:function(){for(var t=[],n=0;e.length>n;n++)t.push(e[n].key);return t},top:function(){return e[e.length-1]},remove:function(t){for(var n=-1,a=0;e.length>a;a++)if(t==e[a].key){n=a;break}return e.splice(n,1)[0]},removeTop:function(){return e.splice(e.length-1,1)[0]},length:function(){return e.length}}}}}).directive("modalBackdrop",["$modalStack","$timeout",function(e,t){return{restrict:"EA",replace:!0,templateUrl:"template/modal/backdrop.html",link:function(n){t(function(){n.animate=!0}),n.close=function(t){var n=e.getTop();n&&n.value.backdrop&&"static"!=n.value.backdrop&&(t.preventDefault(),t.stopPropagation(),e.dismiss(n.key,"backdrop click"))}}}}]).directive("modalWindow",["$timeout",function(e){return{restrict:"EA",scope:{index:"@"},replace:!0,transclude:!0,templateUrl:"template/modal/window.html",link:function(t,n,a){t.windowClass=a.windowClass||"",e(function(){t.animate=!0})}}}]).factory("$modalStack",["$document","$compile","$rootScope","$$stackedMap",function(e,t,n,a){function i(){for(var e=-1,t=u.keys(),n=0;t.length>n;n++)u.get(t[n]).value.backdrop&&(e=n);return e}function r(e){var t=u.get(e).value;u.remove(e),t.modalDomEl.remove(),-1==i()&&(l.remove(),l=void 0),t.modalScope.$destroy()}var o,l,s=n.$new(!0),c=e.find("body").eq(0),u=a.createNew(),p={};return n.$watch(i,function(e){s.index=e}),e.bind("keydown",function(e){var t;27===e.which&&(t=u.top(),t&&t.value.keyboard&&n.$apply(function(){p.dismiss(t.key)}))}),p.open=function(e,n){u.add(e,{deferred:n.deferred,modalScope:n.scope,backdrop:n.backdrop,keyboard:n.keyboard});var a=angular.element("
    ");a.attr("window-class",n.windowClass),a.attr("index",u.length()-1),a.html(n.content);var r=t(a)(n.scope);u.top().value.modalDomEl=r,c.append(r),i()>=0&&!l&&(o=angular.element("
    "),l=t(o)(s),c.append(l))},p.close=function(e,t){var n=u.get(e);n&&(n.value.deferred.resolve(t),r(e))},p.dismiss=function(e,t){var n=u.get(e).value;n&&(n.deferred.reject(t),r(e))},p.getTop=function(){return u.top()},p}]).provider("$modal",function(){var e={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(t,n,a,i,r,o,l){function s(e){return e.template?a.when(e.template):i.get(e.templateUrl,{cache:r}).then(function(e){return e.data})}function c(e){var n=[];return angular.forEach(e,function(e){(angular.isFunction(e)||angular.isArray(e))&&n.push(a.when(t.invoke(e)))}),n}var u={};return u.open=function(t){var i=a.defer(),r=a.defer(),u={result:i.promise,opened:r.promise,close:function(e){l.close(u,e)},dismiss:function(e){l.dismiss(u,e)}};if(t=angular.extend({},e.options,t),t.resolve=t.resolve||{},!t.template&&!t.templateUrl)throw Error("One of template or templateUrl options is required.");var p=a.all([s(t)].concat(c(t.resolve)));return p.then(function(e){var a=(t.scope||n).$new();a.$close=u.close,a.$dismiss=u.dismiss;var r,s={},c=1;t.controller&&(s.$scope=a,s.$modalInstance=u,angular.forEach(t.resolve,function(t,n){s[n]=e[c++]}),r=o(t.controller,s)),l.open(u,{scope:a,deferred:i,content:e[0],backdrop:t.backdrop,keyboard:t.keyboard,windowClass:t.windowClass})},function(e){i.reject(e)}),p.then(function(){r.resolve(!0)},function(){r.reject(!1)}),u},u}]};return e}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse","$interpolate",function(e,t,n,a){var i=this;this.init=function(a){t.itemsPerPage?e.$parent.$watch(n(t.itemsPerPage),function(t){i.itemsPerPage=parseInt(t,10),e.totalPages=i.calculateTotalPages()}):this.itemsPerPage=a},this.noPrevious=function(){return 1===this.page},this.noNext=function(){return this.page===e.totalPages},this.isActive=function(e){return this.page===e},this.calculateTotalPages=function(){return 1>this.itemsPerPage?1:Math.ceil(e.totalItems/this.itemsPerPage)},this.getAttributeValue=function(t,n,i){return angular.isDefined(t)?i?a(t)(e.$parent):e.$parent.$eval(t):n},this.render=function(){this.page=parseInt(e.page,10)||1,e.pages=this.getPages(this.page,e.totalPages)},e.selectPage=function(t){!i.isActive(t)&&t>0&&e.totalPages>=t&&(e.page=t,e.onSelectPage({page:t}))},e.$watch("totalItems",function(){e.totalPages=i.calculateTotalPages()}),e.$watch("totalPages",function(n){t.numPages&&(e.numPages=n),i.page>n?e.selectPage(n):i.render()}),e.$watch("page",function(){i.render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(e,t){return{restrict:"EA",scope:{page:"=",totalItems:"=",onSelectPage:" &",numPages:"="},controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(n,a,i,r){function o(e,t,n,a){return{number:e,text:t,active:n,disabled:a}}var l,s=r.getAttributeValue(i.boundaryLinks,t.boundaryLinks),c=r.getAttributeValue(i.directionLinks,t.directionLinks),u=r.getAttributeValue(i.firstText,t.firstText,!0),p=r.getAttributeValue(i.previousText,t.previousText,!0),d=r.getAttributeValue(i.nextText,t.nextText,!0),f=r.getAttributeValue(i.lastText,t.lastText,!0),m=r.getAttributeValue(i.rotate,t.rotate);r.init(t.itemsPerPage),i.maxSize&&n.$parent.$watch(e(i.maxSize),function(e){l=parseInt(e,10),r.render()}),r.getPages=function(e,t){var n=[],a=1,i=t,g=angular.isDefined(l)&&t>l;g&&(m?(a=Math.max(e-Math.floor(l/2),1),i=a+l-1,i>t&&(i=t,a=i-l+1)):(a=(Math.ceil(e/l)-1)*l+1,i=Math.min(a+l-1,t)));for(var h=a;i>=h;h++){var v=o(h,h,r.isActive(h),!1);n.push(v)}if(g&&!m){if(a>1){var b=o(a-1,"...",!1,!1);n.unshift(b)}if(t>i){var $=o(i+1,"...",!1,!1);n.push($)}}if(c){var y=o(e-1,p,!1,r.noPrevious());n.unshift(y);var w=o(e+1,d,!1,r.noNext());n.push(w)}if(s){var k=o(1,u,!1,r.noPrevious());n.unshift(k);var D=o(t,f,!1,r.noNext());n.push(D)}return n}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(e){return{restrict:"EA",scope:{page:"=",totalItems:"=",onSelectPage:" &",numPages:"="},controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(t,n,a,i){function r(e,t,n,a,i){return{number:e,text:t,disabled:n,previous:s&&a,next:s&&i}}var o=i.getAttributeValue(a.previousText,e.previousText,!0),l=i.getAttributeValue(a.nextText,e.nextText,!0),s=i.getAttributeValue(a.align,e.align);i.init(e.itemsPerPage),i.getPages=function(e){return[r(e-1,o,i.noPrevious(),!0,!1),r(e+1,l,i.noNext(),!1,!0)]}}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function e(e){var t=/[A-Z]/g,n="-";return e.replace(t,function(e,t){return(t?n:"")+e.toLowerCase()})}var t={placement:"top",animation:!0,popupDelay:0},n={mouseenter:"mouseleave",click:"click",focus:"blur"},a={};this.options=function(e){angular.extend(a,e)},this.setTriggers=function(e){angular.extend(n,e)},this.$get=["$window","$compile","$timeout","$parse","$document","$position","$interpolate",function(i,r,o,l,s,c,u){return function(i,p,d){function f(e){var t=e||m.trigger||d,a=n[t]||t;return{show:t,hide:a}}var m=angular.extend({},t,a),g=e(i),h=u.startSymbol(),v=u.endSymbol(),b="<"+g+"-popup "+'title="'+h+"tt_title"+v+'" '+'content="'+h+"tt_content"+v+'" '+'placement="'+h+"tt_placement"+v+'" '+'animation="tt_animation()" '+'is-open="tt_isOpen"'+">"+"";return{restrict:"EA",scope:!0,link:function(e,t,n){function a(){e.tt_isOpen?d():u()}function u(){e.tt_popupDelay?$=o(g,e.tt_popupDelay):e.$apply(g)}function d(){e.$apply(function(){h()})}function g(){var n,a,i,r;if(e.tt_content){switch(v&&o.cancel(v),w.css({top:0,left:0,display:"block"}),k?(y=y||s.find("body"),y.append(w)):t.after(w),n=k?c.offset(t):c.position(t),a=w.prop("offsetWidth"),i=w.prop("offsetHeight"),e.tt_placement){case"right":r={top:n.top+n.height/2-i/2,left:n.left+n.width};break;case"bottom":r={top:n.top+n.height,left:n.left+n.width/2-a/2};break;case"left":r={top:n.top+n.height/2-i/2,left:n.left-a};break;default:r={top:n.top-i,left:n.left+n.width/2-a/2}}r.top+="px",r.left+="px",w.css(r),e.tt_isOpen=!0}}function h(){e.tt_isOpen=!1,o.cancel($),angular.isDefined(e.tt_animation)&&e.tt_animation()?v=o(function(){w.remove()},500):w.remove()}var v,$,y,w=r(b)(e),k=angular.isDefined(m.appendToBody)?m.appendToBody:!1,D=f(void 0),x=!1;e.tt_isOpen=!1,n.$observe(i,function(t){e.tt_content=t}),n.$observe(p+"Title",function(t){e.tt_title=t}),n.$observe(p+"Placement",function(t){e.tt_placement=angular.isDefined(t)?t:m.placement}),n.$observe(p+"Animation",function(t){e.tt_animation=angular.isDefined(t)?l(t):function(){return m.animation}}),n.$observe(p+"PopupDelay",function(t){var n=parseInt(t,10);e.tt_popupDelay=isNaN(n)?m.popupDelay:n}),n.$observe(p+"Trigger",function(e){x&&(t.unbind(D.show,u),t.unbind(D.hide,d)),D=f(e),D.show===D.hide?t.bind(D.show,a):(t.bind(D.show,u),t.bind(D.hide,d)),x=!0}),n.$observe(p+"AppendToBody",function(t){k=angular.isDefined(t)?l(t)(e):k}),k&&e.$on("$locationChangeSuccess",function(){e.tt_isOpen&&h()}),e.$on("$destroy",function(){e.tt_isOpen?h():w.remove()})}}}}]}).directive("tooltipPopup",function(){return{restrict:"E",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(e){return e("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"E",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(e){return e("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$compile","$timeout","$parse","$window","$tooltip",function(e,t,n,a,i){return i("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",["ui.bootstrap.transition"]).constant("progressConfig",{animate:!0,autoType:!1,stackedTypes:["success","info","warning","danger"]}).controller("ProgressBarController",["$scope","$attrs","progressConfig",function(e,t,n){function a(e){return o[e]}var i=angular.isDefined(t.animate)?e.$eval(t.animate):n.animate,r=angular.isDefined(t.autoType)?e.$eval(t.autoType):n.autoType,o=angular.isDefined(t.stackedTypes)?e.$eval("["+t.stackedTypes+"]"):n.stackedTypes;this.makeBar=function(e,t,n){var o=angular.isObject(e)?e.value:e||0,l=angular.isObject(t)?t.value:t||0,s=angular.isObject(e)&&angular.isDefined(e.type)?e.type:r?a(n||0):null;return{from:l,to:o,type:s,animate:i}},this.addBar=function(t){e.bars.push(t),e.totalPercent+=t.to},this.clearBars=function(){e.bars=[],e.totalPercent=0},this.clearBars()}]).directive("progress",function(){return{restrict:"EA",replace:!0,controller:"ProgressBarController",scope:{value:"=percent",onFull:"&",onEmpty:"&"},templateUrl:"template/progressbar/progress.html",link:function(e,t,n,a){e.$watch("value",function(e,t){if(a.clearBars(),angular.isArray(e))for(var n=0,i=e.length;i>n;n++)a.addBar(a.makeBar(e[n],t[n],n));else a.addBar(a.makeBar(e,t))},!0),e.$watch("totalPercent",function(t){t>=100?e.onFull():0>=t&&e.onEmpty()},!0)}}}).directive("progressbar",["$transition",function(e){return{restrict:"EA",replace:!0,scope:{width:"=",old:"=",type:"=",animate:"="},templateUrl:"template/progressbar/bar.html",link:function(t,n){t.$watch("width",function(a){t.animate?(n.css("width",t.old+"%"),e(n,{width:a+"%"})):n.css("width",a+"%")})}}}]),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","$parse","ratingConfig",function(e,t,n,a){this.maxRange=angular.isDefined(t.max)?e.$parent.$eval(t.max):a.max,this.stateOn=angular.isDefined(t.stateOn)?e.$parent.$eval(t.stateOn):a.stateOn,this.stateOff=angular.isDefined(t.stateOff)?e.$parent.$eval(t.stateOff):a.stateOff,this.createDefaultRange=function(e){for(var t={stateOn:this.stateOn,stateOff:this.stateOff},n=Array(e),a=0;e>a;a++)n[a]=t;return n},this.normalizeRange=function(e){for(var t=0,n=e.length;n>t;t++)e[t].stateOn=e[t].stateOn||this.stateOn,e[t].stateOff=e[t].stateOff||this.stateOff;return e},e.range=angular.isDefined(t.ratingStates)?this.normalizeRange(angular.copy(e.$parent.$eval(t.ratingStates))):this.createDefaultRange(this.maxRange),e.rate=function(t){e.readonly||e.value===t||(e.value=t)},e.enter=function(t){e.readonly||(e.val=t),e.onHover({value:t})},e.reset=function(){e.val=angular.copy(e.value),e.onLeave()},e.$watch("value",function(t){e.val=t}),e.readonly=!1,t.readonly&&e.$parent.$watch(n(t.readonly),function(t){e.readonly=!!t})}]).directive("rating",function(){return{restrict:"EA",scope:{value:"=",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0}}),angular.module("ui.bootstrap.tabs",[]).directive("tabs",function(){return function(){throw Error("The `tabs` directive is deprecated, please migrate to `tabset`. Instructions can be found at http://github.com/angular-ui/bootstrap/tree/master/CHANGELOG.md")}}).controller("TabsetController",["$scope","$element",function(e){var t=this,n=t.tabs=e.tabs=[];t.select=function(e){angular.forEach(n,function(e){e.active=!1}),e.active=!0},t.addTab=function(e){n.push(e),(1===n.length||e.active)&&t.select(e)},t.removeTab=function(e){var a=n.indexOf(e);if(e.active&&n.length>1){var i=a==n.length-1?a-1:a+1;t.select(n[i])}n.splice(a,1)}}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,require:"^tabset",scope:{},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",compile:function(e,t,n){return function(e,t,a,i){e.vertical=angular.isDefined(a.vertical)?e.$parent.$eval(a.vertical):!1,e.type=angular.isDefined(a.type)?e.$parent.$eval(a.type):"tabs",e.direction=angular.isDefined(a.direction)?e.$parent.$eval(a.direction):"top",e.tabsAbove="below"!=e.direction,i.$scope=e,i.$transcludeFn=n}}}}).directive("tab",["$parse","$http","$templateCache","$compile",function(e){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(t,n,a){return function(t,n,i,r){var o,l; +i.active?(o=e(i.active),l=o.assign,t.$parent.$watch(o,function(e){t.active=!!e}),t.active=o(t.$parent)):l=o=angular.noop,t.$watch("active",function(e){l(t.$parent,e),e?(r.select(t),t.onSelect()):t.onDeselect()}),t.disabled=!1,i.disabled&&t.$parent.$watch(e(i.disabled),function(e){t.disabled=!!e}),t.select=function(){t.disabled||(t.active=!0)},r.addTab(t),t.$on("$destroy",function(){r.removeTab(t)}),t.active&&l(t.$parent,!0),t.$transcludeFn=a}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(e,t){e.$watch("headingElement",function(e){e&&(t.html(""),t.append(e))})}}}]).directive("tabContentTransclude",["$compile","$parse",function(){function e(e){return e.tagName&&(e.hasAttribute("tab-heading")||e.hasAttribute("data-tab-heading")||"tab-heading"===e.tagName.toLowerCase()||"data-tab-heading"===e.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(t,n,a){var i=t.$eval(a.tabContentTransclude);i.$transcludeFn(i.$parent,function(t){angular.forEach(t,function(t){e(t)?i.headingElement=t:n.append(t)})})}}}]).directive("tabsetTitles",["$http",function(){return{restrict:"A",require:"^tabset",templateUrl:"template/tabs/tabset-titles.html",replace:!0,link:function(e,t,n,a){e.$eval(n.tabsetTitles)?a.$transcludeFn(a.$scope.$parent,function(e){t.append(e)}):t.remove()}}}]),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:["AM","PM"],readonlyInput:!1,mousewheel:!0}).directive("timepicker",["$parse","$log","timepickerConfig",function(e,t,n){return{restrict:"EA",require:"?^ngModel",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,i,r,o){function l(){var e=parseInt(a.hours,10),t=a.showMeridian?e>0&&13>e:e>=0&&24>e;return t?(a.showMeridian&&(12===e&&(e=0),a.meridian===g[1]&&(e+=12)),e):void 0}function s(){var e=parseInt(a.minutes,10);return e>=0&&60>e?e:void 0}function c(e){return angular.isDefined(e)&&2>(""+e).length?"0"+e:e}function u(e){p(),o.$setViewValue(new Date(m)),d(e)}function p(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function d(e){var t=m.getHours(),n=m.getMinutes();a.showMeridian&&(t=0===t||12===t?12:t%12),a.hours="h"===e?t:c(t),a.minutes="m"===e?n:c(n),a.meridian=12>m.getHours()?g[0]:g[1]}function f(e){var t=new Date(m.getTime()+6e4*e);m.setHours(t.getHours(),t.getMinutes()),u()}if(o){var m=new Date,g=n.meridians,h=n.hourStep;r.hourStep&&a.$parent.$watch(e(r.hourStep),function(e){h=parseInt(e,10)});var v=n.minuteStep;r.minuteStep&&a.$parent.$watch(e(r.minuteStep),function(e){v=parseInt(e,10)}),a.showMeridian=n.showMeridian,r.showMeridian&&a.$parent.$watch(e(r.showMeridian),function(e){if(a.showMeridian=!!e,o.$error.time){var t=l(),n=s();angular.isDefined(t)&&angular.isDefined(n)&&(m.setHours(t),u())}else d()});var b=i.find("input"),$=b.eq(0),y=b.eq(1),w=angular.isDefined(r.mousewheel)?a.$eval(r.mousewheel):n.mousewheel;if(w){var k=function(e){e.originalEvent&&(e=e.originalEvent);var t=e.wheelDelta?e.wheelDelta:-e.deltaY;return e.detail||t>0};$.bind("mousewheel wheel",function(e){a.$apply(k(e)?a.incrementHours():a.decrementHours()),e.preventDefault()}),y.bind("mousewheel wheel",function(e){a.$apply(k(e)?a.incrementMinutes():a.decrementMinutes()),e.preventDefault()})}if(a.readonlyInput=angular.isDefined(r.readonlyInput)?a.$eval(r.readonlyInput):n.readonlyInput,a.readonlyInput)a.updateHours=angular.noop,a.updateMinutes=angular.noop;else{var D=function(e,t){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(e)&&(a.invalidHours=e),angular.isDefined(t)&&(a.invalidMinutes=t)};a.updateHours=function(){var e=l();angular.isDefined(e)?(m.setHours(e),u("h")):D(!0)},$.bind("blur",function(){!a.validHours&&10>a.hours&&a.$apply(function(){a.hours=c(a.hours)})}),a.updateMinutes=function(){var e=s();angular.isDefined(e)?(m.setMinutes(e),u("m")):D(void 0,!0)},y.bind("blur",function(){!a.invalidMinutes&&10>a.minutes&&a.$apply(function(){a.minutes=c(a.minutes)})})}o.$render=function(){var e=o.$modelValue?new Date(o.$modelValue):null;isNaN(e)?(o.$setValidity("time",!1),t.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.')):(e&&(m=e),p(),d())},a.incrementHours=function(){f(60*h)},a.decrementHours=function(){f(60*-h)},a.incrementMinutes=function(){f(v)},a.decrementMinutes=function(){f(-v)},a.toggleMeridian=function(){f(720*(12>m.getHours()?1:-1))}}}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(e){var t=/^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;return{parse:function(n){var a=n.match(t);if(!a)throw Error("Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_' but got '"+n+"'.");return{itemName:a[3],source:e(a[4]),viewMapper:e(a[2]||a[1]),modelMapper:e(a[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(e,t,n,a,i,r,o){var l=[9,13,27,38,40];return{require:"ngModel",link:function(s,c,u,p){var d=s.$eval(u.typeaheadMinLength)||1,f=s.$eval(u.typeaheadWaitMs)||0,m=s.$eval(u.typeaheadEditable)!==!1,g=t(u.typeaheadLoading).assign||angular.noop,h=t(u.typeaheadOnSelect),v=u.typeaheadInputFormatter?t(u.typeaheadInputFormatter):void 0,b=t(u.ngModel).assign,$=o.parse(u.typeahead),y=angular.element("");y.attr({matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(u.typeaheadTemplateUrl)&&y.attr("template-url",u.typeaheadTemplateUrl);var w=s.$new();s.$on("$destroy",function(){w.$destroy()});var k=function(){w.matches=[],w.activeIdx=-1},D=function(e){var t={$viewValue:e};g(s,!0),n.when($.source(w,t)).then(function(n){if(e===p.$viewValue){if(n.length>0){w.activeIdx=0,w.matches.length=0;for(var a=0;n.length>a;a++)t[$.itemName]=n[a],w.matches.push({label:$.viewMapper(w,t),model:n[a]});w.query=e,w.position=r.position(c),w.position.top=w.position.top+c.prop("offsetHeight")}else k();g(s,!1)}},function(){k(),g(s,!1)})};k(),w.query=void 0;var x;p.$parsers.unshift(function(e){return k(),e&&e.length>=d&&(f>0?(x&&a.cancel(x),x=a(function(){D(e)},f)):D(e)),m?e:(p.$setValidity("editable",!1),void 0)}),p.$formatters.push(function(e){var t,n,a={};return v?(a.$model=e,v(s,a)):(a[$.itemName]=e,t=$.viewMapper(s,a),a[$.itemName]=void 0,n=$.viewMapper(s,a),t!==n?t:e)}),w.select=function(e){var t,n,a={};a[$.itemName]=n=w.matches[e].model,t=$.modelMapper(s,a),b(s,t),p.$setValidity("editable",!0),h(s,{$item:n,$model:t,$label:$.viewMapper(s,a)}),k(),c[0].focus()},c.bind("keydown",function(e){0!==w.matches.length&&-1!==l.indexOf(e.which)&&(e.preventDefault(),40===e.which?(w.activeIdx=(w.activeIdx+1)%w.matches.length,w.$digest()):38===e.which?(w.activeIdx=(w.activeIdx?w.activeIdx:w.matches.length)-1,w.$digest()):13===e.which||9===e.which?w.$apply(function(){w.select(w.activeIdx)}):27===e.which&&(e.stopPropagation(),k(),w.$digest()))});var T=function(e){c[0]!==e.target&&(k(),w.$digest())};i.bind("click",T),s.$on("$destroy",function(){i.unbind("click",T)}),c.after(e(y)(w))}}}]).directive("typeaheadPopup",function(){return{restrict:"E",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(e,t,n){e.templateUrl=n.templateUrl,e.isOpen=function(){return e.matches.length>0},e.isActive=function(t){return e.active==t},e.selectActive=function(t){e.active=t},e.selectMatch=function(t){e.select({activeIdx:t})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(e,t,n,a){return{restrict:"E",scope:{index:"=",match:"=",query:"="},link:function(i,r,o){var l=a(o.templateUrl)(i.$parent)||"template/typeahead/typeahead-match.html";e.get(l,{cache:t}).success(function(e){r.replaceWith(n(e.trim())(i))})}}}]).filter("typeaheadHighlight",function(){function e(e){return e.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(t,n){return n?t.replace(RegExp(e(n),"gi"),"$&"):t}}),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(e){e.put("template/accordion/accordion-group.html",'
    \n \n
    \n
    \n
    ')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(e){e.put("template/accordion/accordion.html",'
    ')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(e){e.put("template/alert/alert.html","
    \n \n
    \n
    \n")}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(e){e.put("template/carousel/carousel.html",'\n')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(e){e.put("template/carousel/slide.html","
    \n")}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(e){e.put("template/datepicker/datepicker.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
    #{{label}}
    {{ getWeekNumber(row) }}\n \n
    \n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(e){e.put("template/datepicker/popup.html",'')}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(e){e.put("template/modal/backdrop.html",'')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(e){e.put("template/modal/window.html",'')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(e){e.put("template/pagination/pager.html",'
    \n \n
    \n')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(e){e.put("template/pagination/pagination.html",'\n')}]),angular.module("template/tooltip/tooltip-html-unsafe-popup.html",[]).run(["$templateCache",function(e){e.put("template/tooltip/tooltip-html-unsafe-popup.html",'
    \n
    \n
    \n
    \n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(e){e.put("template/tooltip/tooltip-popup.html",'
    \n
    \n
    \n
    \n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(e){e.put("template/popover/popover.html",'
    \n
    \n\n
    \n

    \n
    \n
    \n
    \n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(e){e.put("template/progressbar/bar.html",'
    ')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(e){e.put("template/progressbar/progress.html",'
    ')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(e){e.put("template/rating/rating.html",'\n \n')}]),angular.module("template/tabs/pane.html",[]).run(["$templateCache",function(e){e.put("template/tabs/pane.html",'
    \n')}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(e){e.put("template/tabs/tab.html",'
  • \n {{heading}}\n
  • \n')}]),angular.module("template/tabs/tabs.html",[]).run(["$templateCache",function(e){e.put("template/tabs/tabs.html",'
    \n \n
    \n
    \n')}]),angular.module("template/tabs/tabset-titles.html",[]).run(["$templateCache",function(e){e.put("template/tabs/tabset-titles.html","
      \n
    \n")}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(e){e.put("template/tabs/tabset.html",'\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(e){e.put("template/timepicker/timepicker.html",'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
     
    :
     
    ')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(e){e.put("template/typeahead/typeahead-match.html",'')}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(e){e.put("template/typeahead/typeahead-popup.html",'')}]),angular.module("template/typeahead/typeahead.html",[]).run(["$templateCache",function(e){e.put("template/typeahead/typeahead.html",'')}]); \ No newline at end of file diff --git a/ui-bootstrap.js b/ui-bootstrap.js index 132a08e..1bcdbab 100644 --- a/ui-bootstrap.js +++ b/ui-bootstrap.js @@ -1,4 +1,4 @@ -angular.module("ui.bootstrap", ["ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dialog","ui.bootstrap.dropdownToggle","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"]); +angular.module("ui.bootstrap", ["ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdownToggle","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"]); angular.module('ui.bootstrap.transition', []) /** @@ -336,6 +336,16 @@ angular.module("ui.bootstrap.alert", []).directive('alert', function () { }; }); +angular.module('ui.bootstrap.bindHtml', []) + + .directive('bindHtmlUnsafe', function () { + return function (scope, element, attr) { + element.addClass('ng-binding').data('$binding', attr.bindHtmlUnsafe); + scope.$watch(attr.bindHtmlUnsafe, function bindHtmlUnsafeWatchAction(value) { + element.html(value || ''); + }); + }; + }); angular.module('ui.bootstrap.buttons', []) .constant('buttonConfig', { @@ -407,7 +417,7 @@ angular.module('ui.bootstrap.buttons', []) /** * @ngdoc overview * @name ui.bootstrap.carousel -* +* * @description * AngularJS version of an image carousel. * @@ -438,10 +448,10 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition']) } function goNext() { //If we have a slide to transition from and we have a transition type and we're allowed, go - if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) { + if (self.currentSlide && angular.isString(direction) && !$scope.noTransition && nextSlide.$element) { //We shouldn't do class manip in here, but it's the same weird thing bootstrap does. need to fix sometime nextSlide.$element.addClass(direction); - nextSlide.$element[0].offsetWidth = nextSlide.$element[0].offsetWidth; //force reflow + var reflow = nextSlide.$element[0].offsetWidth; //force reflow //Set all other slides to stop doing their stuff for the new transition angular.forEach(slides, function(slide) { @@ -480,7 +490,7 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition']) $scope.next = function() { var newIndex = (currentIndex + 1) % slides.length; - + //Prevent this user-triggered transition from occurring if there is already one in progress if (!$scope.$currentTransition) { return self.select(slides[newIndex], 'next'); @@ -489,7 +499,7 @@ angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition']) $scope.prev = function() { var newIndex = currentIndex - 1 < 0 ? slides.length - 1 : currentIndex - 1; - + //Prevent this user-triggered transition from occurring if there is already one in progress if (!$scope.$currentTransition) { return self.select(slides[newIndex], 'prev'); @@ -706,7 +716,7 @@ function CarouselDemoCtrl($scope) { var lastValue = scope.active = getActive(scope.$parent); scope.$watch(function parentActiveWatch() { var parentActive = getActive(scope.$parent); - + if (parentActive !== scope.active) { // we are out of sync and need to copy if (parentActive !== lastValue) { @@ -746,13 +756,6 @@ angular.module('ui.bootstrap.position', []) */ .factory('$position', ['$document', '$window', function ($document, $window) { - var mouseX, mouseY; - - $document.bind('mousemove', function mouseMoved(event) { - mouseX = event.pageX; - mouseY = event.pageY; - }); - function getStyle(el, cssprop) { if (el.currentStyle) { //IE return el.currentStyle[cssprop]; @@ -816,16 +819,9 @@ angular.module('ui.bootstrap.position', []) return { width: element.prop('offsetWidth'), height: element.prop('offsetHeight'), - top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop), - left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft) + top: boundingClientRect.top + ($window.pageYOffset || $document[0].body.scrollTop || $document[0].documentElement.scrollTop), + left: boundingClientRect.left + ($window.pageXOffset || $document[0].body.scrollLeft || $document[0].documentElement.scrollLeft) }; - }, - - /** - * Provides the coordinates of the mouse - */ - mouse: function () { - return {x: mouseX, y: mouseY}; } }; }]); @@ -1104,26 +1100,9 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon scope.$destroy(); }); - function formatDate(value) { - return (value) ? dateFilter(value, dateFormat) : null; - } - ngModel.$formatters.push(formatDate); - - // TODO: reverse from dateFilter string to Date object - function parseDate(value) { - if ( value ) { - var date = new Date(value); - if (!isNaN(date)) { - return date; - } - } - return value; - } - ngModel.$parsers.push(parseDate); - var getIsOpen, setIsOpen; - if ( attrs.open ) { - getIsOpen = $parse(attrs.open); + if ( attrs.isOpen ) { + getIsOpen = $parse(attrs.isOpen); setIsOpen = getIsOpen.assign; originalScope.$watch(getIsOpen, function updateOpen(value) { @@ -1165,33 +1144,58 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon datepickerEl.attr(angular.extend({}, originalScope.$eval(attrs.datepickerOptions))); } - var $setModelValue = $parse(attrs.ngModel).assign; + // TODO: reverse from dateFilter string to Date object + function parseDate(viewValue) { + if (!viewValue) { + ngModel.$setValidity('date', true); + return null; + } else if (angular.isDate(viewValue)) { + ngModel.$setValidity('date', true); + return viewValue; + } else if (angular.isString(viewValue)) { + var date = new Date(viewValue); + if (isNaN(date)) { + ngModel.$setValidity('date', false); + return undefined; + } else { + ngModel.$setValidity('date', true); + return date; + } + } else { + ngModel.$setValidity('date', false); + return undefined; + } + } + ngModel.$parsers.unshift(parseDate); // Inner change scope.dateSelection = function() { - $setModelValue(originalScope, scope.date); + ngModel.$setViewValue(scope.date); + ngModel.$render(); + if (closeOnDateSelection) { setOpen( false ); } }; + element.bind('input change keyup', function() { + scope.$apply(function() { + updateCalendar(); + }); + }); + // Outter change - scope.$watch(function() { - return ngModel.$modelValue; - }, function(value) { - if (angular.isString(value)) { - var date = parseDate(value); - - if (value && !date) { - $setModelValue(originalScope, null); - throw new Error(value + ' cannot be parsed to a date object.'); - } else { - value = date; - } - } - scope.date = value; + ngModel.$render = function() { + var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : ''; + element.val(date); + + updateCalendar(); + }; + + function updateCalendar() { + scope.date = ngModel.$modelValue; updatePosition(); - }); + } function addWatchableAttribute(attribute, scopeProperty, datepickerAttribute) { if (attribute) { @@ -1218,15 +1222,22 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon scope.position.top = scope.position.top + element.prop('offsetHeight'); } + var documentBindingInitialized = false, elementFocusInitialized = false; scope.$watch('isOpen', function(value) { if (value) { updatePosition(); $document.bind('click', documentClickBind); - element.unbind('focus', elementFocusBind); - element.focus(); + if(elementFocusInitialized) { + element.unbind('focus', elementFocusBind); + } + element[0].focus(); + documentBindingInitialized = true; } else { - $document.unbind('click', documentClickBind); + if(documentBindingInitialized) { + $document.unbind('click', documentClickBind); + } element.bind('focus', elementFocusBind); + elementFocusInitialized = true; } if ( setIsOpen ) { @@ -1234,6 +1245,8 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon } }); + var $setModelValue = $parse(attrs.ngModel).assign; + scope.today = function() { $setModelValue(originalScope, new Date()); }; @@ -1260,286 +1273,6 @@ function ($compile, $parse, $document, $position, dateFilter, datepickerPopupCon } }; }]); -// The `$dialogProvider` can be used to configure global defaults for your -// `$dialog` service. -var dialogModule = angular.module('ui.bootstrap.dialog', ['ui.bootstrap.transition']); - -dialogModule.controller('MessageBoxController', ['$scope', 'dialog', 'model', function($scope, dialog, model){ - $scope.title = model.title; - $scope.message = model.message; - $scope.buttons = model.buttons; - $scope.close = function(res){ - dialog.close(res); - }; -}]); - -dialogModule.provider("$dialog", function(){ - - // The default options for all dialogs. - var defaults = { - backdrop: true, - dialogClass: 'modal', - backdropClass: 'modal-backdrop', - transitionClass: 'fade', - triggerClass: 'in', - resolve:{}, - backdropFade: false, - dialogFade:false, - keyboard: true, // close with esc key - backdropClick: true // only in conjunction with backdrop=true - /* other options: template, templateUrl, controller */ - }; - - var globalOptions = {}; - - var activeBackdrops = {value : 0}; - - // The `options({})` allows global configuration of all dialogs in the application. - // - // var app = angular.module('App', ['ui.bootstrap.dialog'], function($dialogProvider){ - // // don't close dialog when backdrop is clicked by default - // $dialogProvider.options({backdropClick: false}); - // }); - this.options = function(value){ - globalOptions = value; - }; - - // Returns the actual `$dialog` service that is injected in controllers - this.$get = ["$http", "$document", "$compile", "$rootScope", "$controller", "$templateCache", "$q", "$transition", "$injector", - function ($http, $document, $compile, $rootScope, $controller, $templateCache, $q, $transition, $injector) { - - var body = $document.find('body'); - - function createElement(clazz) { - var el = angular.element("
    "); - el.addClass(clazz); - return el; - } - - // The `Dialog` class represents a modal dialog. The dialog class can be invoked by providing an options object - // containing at lest template or templateUrl and controller: - // - // var d = new Dialog({templateUrl: 'foo.html', controller: 'BarController'}); - // - // Dialogs can also be created using templateUrl and controller as distinct arguments: - // - // var d = new Dialog('path/to/dialog.html', MyDialogController); - function Dialog(opts) { - - var self = this, options = this.options = angular.extend({}, defaults, globalOptions, opts); - this._open = false; - - this.backdropEl = createElement(options.backdropClass); - if(options.backdropFade){ - this.backdropEl.addClass(options.transitionClass); - this.backdropEl.removeClass(options.triggerClass); - } - - this.modalEl = createElement(options.dialogClass); - if(options.dialogFade){ - this.modalEl.addClass(options.transitionClass); - this.modalEl.removeClass(options.triggerClass); - } - - this.handledEscapeKey = function(e) { - if (e.which === 27) { - self.close(); - e.preventDefault(); - self.$scope.$apply(); - } - }; - - this.handleBackDropClick = function(e) { - self.close(); - e.preventDefault(); - self.$scope.$apply(); - }; - } - - // The `isOpen()` method returns wether the dialog is currently visible. - Dialog.prototype.isOpen = function(){ - return this._open; - }; - - // The `open(templateUrl, controller)` method opens the dialog. - // Use the `templateUrl` and `controller` arguments if specifying them at dialog creation time is not desired. - Dialog.prototype.open = function(templateUrl, controller){ - var self = this, options = this.options; - - if(templateUrl){ - options.templateUrl = templateUrl; - } - if(controller){ - options.controller = controller; - } - - if(!(options.template || options.templateUrl)) { - throw new Error('Dialog.open expected template or templateUrl, neither found. Use options or open method to specify them.'); - } - - this._loadResolves().then(function(locals) { - var $scope = locals.$scope = self.$scope = locals.$scope ? locals.$scope : $rootScope.$new(); - - self.modalEl.html(locals.$template); - - if (self.options.controller) { - var ctrl = $controller(self.options.controller, locals); - self.modalEl.children().data('ngControllerController', ctrl); - } - - $compile(self.modalEl)($scope); - self._addElementsToDom(); - - // trigger tranisitions - setTimeout(function(){ - if(self.options.dialogFade){ self.modalEl.addClass(self.options.triggerClass); } - if(self.options.backdropFade){ self.backdropEl.addClass(self.options.triggerClass); } - }); - - self._bindEvents(); - }); - - this.deferred = $q.defer(); - return this.deferred.promise; - }; - - // closes the dialog and resolves the promise returned by the `open` method with the specified result. - Dialog.prototype.close = function(result){ - var self = this; - var fadingElements = this._getFadingElements(); - - if(fadingElements.length > 0){ - for (var i = fadingElements.length - 1; i >= 0; i--) { - $transition(fadingElements[i], removeTriggerClass).then(onCloseComplete); - } - return; - } - - this._onCloseComplete(result); - - function removeTriggerClass(el){ - el.removeClass(self.options.triggerClass); - } - - function onCloseComplete(){ - if(self._open){ - self._onCloseComplete(result); - } - } - }; - - Dialog.prototype._getFadingElements = function(){ - var elements = []; - if(this.options.dialogFade){ - elements.push(this.modalEl); - } - if(this.options.backdropFade){ - elements.push(this.backdropEl); - } - - return elements; - }; - - Dialog.prototype._bindEvents = function() { - if(this.options.keyboard){ body.bind('keydown', this.handledEscapeKey); } - if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.bind('click', this.handleBackDropClick); } - }; - - Dialog.prototype._unbindEvents = function() { - if(this.options.keyboard){ body.unbind('keydown', this.handledEscapeKey); } - if(this.options.backdrop && this.options.backdropClick){ this.backdropEl.unbind('click', this.handleBackDropClick); } - }; - - Dialog.prototype._onCloseComplete = function(result) { - this._removeElementsFromDom(); - this._unbindEvents(); - - this.deferred.resolve(result); - }; - - Dialog.prototype._addElementsToDom = function(){ - body.append(this.modalEl); - - if(this.options.backdrop) { - if (activeBackdrops.value === 0) { - body.append(this.backdropEl); - } - activeBackdrops.value++; - } - - this._open = true; - }; - - Dialog.prototype._removeElementsFromDom = function(){ - this.modalEl.remove(); - - if(this.options.backdrop) { - activeBackdrops.value--; - if (activeBackdrops.value === 0) { - this.backdropEl.remove(); - } - } - this._open = false; - }; - - // Loads all `options.resolve` members to be used as locals for the controller associated with the dialog. - Dialog.prototype._loadResolves = function(){ - var values = [], keys = [], templatePromise, self = this; - - if (this.options.template) { - templatePromise = $q.when(this.options.template); - } else if (this.options.templateUrl) { - templatePromise = $http.get(this.options.templateUrl, {cache:$templateCache}) - .then(function(response) { return response.data; }); - } - - angular.forEach(this.options.resolve || [], function(value, key) { - keys.push(key); - values.push(angular.isString(value) ? $injector.get(value) : $injector.invoke(value)); - }); - - keys.push('$template'); - values.push(templatePromise); - - return $q.all(values).then(function(values) { - var locals = {}; - angular.forEach(values, function(value, index) { - locals[keys[index]] = value; - }); - locals.dialog = self; - return locals; - }); - }; - - // The actual `$dialog` service that is injected in controllers. - return { - // Creates a new `Dialog` with the specified options. - dialog: function(opts){ - return new Dialog(opts); - }, - // creates a new `Dialog` tied to the default message box template and controller. - // - // Arguments `title` and `message` are rendered in the modal header and body sections respectively. - // The `buttons` array holds an object with the following members for each button to include in the - // modal footer section: - // - // * `result`: the result to pass to the `close` method of the dialog when the button is clicked - // * `label`: the label of the button - // * `cssClass`: additional css class(es) to apply to the button for styling - messageBox: function(title, message, buttons){ - return new Dialog({templateUrl: 'template/dialog/message.html', controller: 'MessageBoxController', resolve: - {model: function() { - return { - title: title, - message: message, - buttons: buttons - }; - } - }}); - } - }; - }]; -}); /* * dropdownToggle - Provides dropdown menu functionality in place of bootstrap js @@ -1593,93 +1326,391 @@ angular.module('ui.bootstrap.dropdownToggle', []).directive('dropdownToggle', [' } }; }]); -angular.module('ui.bootstrap.modal', ['ui.bootstrap.dialog']) -.directive('modal', ['$parse', '$dialog', function($parse, $dialog) { - return { - restrict: 'EA', - terminal: true, - link: function(scope, elm, attrs) { - var opts = angular.extend({}, scope.$eval(attrs.uiOptions || attrs.bsOptions || attrs.options)); - var shownExpr = attrs.modal || attrs.show; - var setClosed; - - // Create a dialog with the template as the contents of the directive - // Add the current scope as the resolve in order to make the directive scope as a dialog controller scope - opts = angular.extend(opts, { - template: elm.html(), - resolve: { $scope: function() { return scope; } } - }); - var dialog = $dialog.dialog(opts); +angular.module('ui.bootstrap.modal', []) - elm.remove(); +/** + * A helper, internal data structure that acts as a map but also allows getting / removing + * elements in the LIFO order + */ + .factory('$$stackedMap', function () { + return { + createNew: function () { + var stack = []; - if (attrs.close) { - setClosed = function() { - $parse(attrs.close)(scope); + return { + add: function (key, value) { + stack.push({ + key: key, + value: value + }); + }, + get: function (key) { + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + return stack[i]; + } + } + }, + keys: function() { + var keys = []; + for (var i = 0; i < stack.length; i++) { + keys.push(stack[i].key); + } + return keys; + }, + top: function () { + return stack[stack.length - 1]; + }, + remove: function (key) { + var idx = -1; + for (var i = 0; i < stack.length; i++) { + if (key == stack[i].key) { + idx = i; + break; + } + } + return stack.splice(idx, 1)[0]; + }, + removeTop: function () { + return stack.splice(stack.length - 1, 1)[0]; + }, + length: function () { + return stack.length; + } }; - } else { - setClosed = function() { - if (angular.isFunction($parse(shownExpr).assign)) { - $parse(shownExpr).assign(scope, false); + } + }; + }) + +/** + * A helper directive for the $modal service. It creates a backdrop element. + */ + .directive('modalBackdrop', ['$modalStack', '$timeout', function ($modalStack, $timeout) { + return { + restrict: 'EA', + replace: true, + templateUrl: 'template/modal/backdrop.html', + link: function (scope, element, attrs) { + + //trigger CSS transitions + $timeout(function () { + scope.animate = true; + }); + + scope.close = function (evt) { + var modal = $modalStack.getTop(); + if (modal && modal.value.backdrop && modal.value.backdrop != 'static') { + evt.preventDefault(); + evt.stopPropagation(); + $modalStack.dismiss(modal.key, 'backdrop click'); } }; } + }; + }]) - scope.$watch(shownExpr, function(isShown, oldShown) { - if (isShown) { - dialog.open().then(function(){ - setClosed(); - }); - } else { - //Make sure it is not opened - if (dialog.isOpen()){ - dialog.close(); + .directive('modalWindow', ['$timeout', function ($timeout) { + return { + restrict: 'EA', + scope: { + index: '@' + }, + replace: true, + transclude: true, + templateUrl: 'template/modal/window.html', + link: function (scope, element, attrs) { + scope.windowClass = attrs.windowClass || ''; + + //trigger CSS transitions + $timeout(function () { + scope.animate = true; + }); + } + }; + }]) + + .factory('$modalStack', ['$document', '$compile', '$rootScope', '$$stackedMap', + function ($document, $compile, $rootScope, $$stackedMap) { + + var backdropjqLiteEl, backdropDomEl; + var backdropScope = $rootScope.$new(true); + var body = $document.find('body').eq(0); + var openedWindows = $$stackedMap.createNew(); + var $modalStack = {}; + + function backdropIndex() { + var topBackdropIndex = -1; + var opened = openedWindows.keys(); + for (var i = 0; i < opened.length; i++) { + if (openedWindows.get(opened[i]).value.backdrop) { + topBackdropIndex = i; } } + return topBackdropIndex; + } + + $rootScope.$watch(backdropIndex, function(newBackdropIndex){ + backdropScope.index = newBackdropIndex; }); - } - }; -}]); + + function removeModalWindow(modalInstance) { + + var modalWindow = openedWindows.get(modalInstance).value; + + //clean up the stack + openedWindows.remove(modalInstance); + + //remove window DOM element + modalWindow.modalDomEl.remove(); + + //remove backdrop if no longer needed + if (backdropIndex() == -1) { + backdropDomEl.remove(); + backdropDomEl = undefined; + } + + //destroy scope + modalWindow.modalScope.$destroy(); + } + + $document.bind('keydown', function (evt) { + var modal; + + if (evt.which === 27) { + modal = openedWindows.top(); + if (modal && modal.value.keyboard) { + $rootScope.$apply(function () { + $modalStack.dismiss(modal.key); + }); + } + } + }); + + $modalStack.open = function (modalInstance, modal) { + + openedWindows.add(modalInstance, { + deferred: modal.deferred, + modalScope: modal.scope, + backdrop: modal.backdrop, + keyboard: modal.keyboard + }); + + var angularDomEl = angular.element('
    '); + angularDomEl.attr('window-class', modal.windowClass); + angularDomEl.attr('index', openedWindows.length() - 1); + angularDomEl.html(modal.content); + + var modalDomEl = $compile(angularDomEl)(modal.scope); + openedWindows.top().value.modalDomEl = modalDomEl; + body.append(modalDomEl); + + if (backdropIndex() >= 0 && !backdropDomEl) { + backdropjqLiteEl = angular.element('
    '); + backdropDomEl = $compile(backdropjqLiteEl)(backdropScope); + body.append(backdropDomEl); + } + }; + + $modalStack.close = function (modalInstance, result) { + var modal = openedWindows.get(modalInstance); + if (modal) { + modal.value.deferred.resolve(result); + removeModalWindow(modalInstance); + } + }; + + $modalStack.dismiss = function (modalInstance, reason) { + var modalWindow = openedWindows.get(modalInstance).value; + if (modalWindow) { + modalWindow.deferred.reject(reason); + removeModalWindow(modalInstance); + } + }; + + $modalStack.getTop = function () { + return openedWindows.top(); + }; + + return $modalStack; + }]) + + .provider('$modal', function () { + + var $modalProvider = { + options: { + backdrop: true, //can be also false or 'static' + keyboard: true + }, + $get: ['$injector', '$rootScope', '$q', '$http', '$templateCache', '$controller', '$modalStack', + function ($injector, $rootScope, $q, $http, $templateCache, $controller, $modalStack) { + + var $modal = {}; + + function getTemplatePromise(options) { + return options.template ? $q.when(options.template) : + $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) { + return result.data; + }); + } + + function getResolvePromises(resolves) { + var promisesArr = []; + angular.forEach(resolves, function (value, key) { + if (angular.isFunction(value) || angular.isArray(value)) { + promisesArr.push($q.when($injector.invoke(value))); + } + }); + return promisesArr; + } + + $modal.open = function (modalOptions) { + + var modalResultDeferred = $q.defer(); + var modalOpenedDeferred = $q.defer(); + + //prepare an instance of a modal to be injected into controllers and returned to a caller + var modalInstance = { + result: modalResultDeferred.promise, + opened: modalOpenedDeferred.promise, + close: function (result) { + $modalStack.close(modalInstance, result); + }, + dismiss: function (reason) { + $modalStack.dismiss(modalInstance, reason); + } + }; + + //merge and clean up options + modalOptions = angular.extend({}, $modalProvider.options, modalOptions); + modalOptions.resolve = modalOptions.resolve || {}; + + //verify options + if (!modalOptions.template && !modalOptions.templateUrl) { + throw new Error('One of template or templateUrl options is required.'); + } + + var templateAndResolvePromise = + $q.all([getTemplatePromise(modalOptions)].concat(getResolvePromises(modalOptions.resolve))); + + + templateAndResolvePromise.then(function resolveSuccess(tplAndVars) { + + var modalScope = (modalOptions.scope || $rootScope).$new(); + modalScope.$close = modalInstance.close; + modalScope.$dismiss = modalInstance.dismiss; + + var ctrlInstance, ctrlLocals = {}; + var resolveIter = 1; + + //controllers + if (modalOptions.controller) { + ctrlLocals.$scope = modalScope; + ctrlLocals.$modalInstance = modalInstance; + angular.forEach(modalOptions.resolve, function (value, key) { + ctrlLocals[key] = tplAndVars[resolveIter++]; + }); + + ctrlInstance = $controller(modalOptions.controller, ctrlLocals); + } + + $modalStack.open(modalInstance, { + scope: modalScope, + deferred: modalResultDeferred, + content: tplAndVars[0], + backdrop: modalOptions.backdrop, + keyboard: modalOptions.keyboard, + windowClass: modalOptions.windowClass + }); + + }, function resolveError(reason) { + modalResultDeferred.reject(reason); + }); + + templateAndResolvePromise.then(function () { + modalOpenedDeferred.resolve(true); + }, function () { + modalOpenedDeferred.reject(false); + }); + + return modalInstance; + }; + + return $modal; + }] + }; + + return $modalProvider; + }); angular.module('ui.bootstrap.pagination', []) -.controller('PaginationController', ['$scope', '$interpolate', function ($scope, $interpolate) { +.controller('PaginationController', ['$scope', '$attrs', '$parse', '$interpolate', function ($scope, $attrs, $parse, $interpolate) { + var self = this; - this.currentPage = 1; + this.init = function(defaultItemsPerPage) { + if ($attrs.itemsPerPage) { + $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) { + self.itemsPerPage = parseInt(value, 10); + $scope.totalPages = self.calculateTotalPages(); + }); + } else { + this.itemsPerPage = defaultItemsPerPage; + } + }; this.noPrevious = function() { - return this.currentPage === 1; + return this.page === 1; }; this.noNext = function() { - return this.currentPage === $scope.numPages; + return this.page === $scope.totalPages; }; this.isActive = function(page) { - return this.currentPage === page; + return this.page === page; }; - this.reset = function() { - $scope.pages = []; - this.currentPage = parseInt($scope.currentPage, 10); + this.calculateTotalPages = function() { + return this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage); + }; - if ( this.currentPage > $scope.numPages ) { - $scope.selectPage($scope.numPages); - } + this.getAttributeValue = function(attribute, defaultValue, interpolate) { + return angular.isDefined(attribute) ? (interpolate ? $interpolate(attribute)($scope.$parent) : $scope.$parent.$eval(attribute)) : defaultValue; + }; + + this.render = function() { + this.page = parseInt($scope.page, 10) || 1; + $scope.pages = this.getPages(this.page, $scope.totalPages); }; - var self = this; $scope.selectPage = function(page) { - if ( ! self.isActive(page) && page > 0 && page <= $scope.numPages) { - $scope.currentPage = page; + if ( ! self.isActive(page) && page > 0 && page <= $scope.totalPages) { + $scope.page = page; $scope.onSelectPage({ page: page }); } }; - this.getAttributeValue = function(attribute, defaultValue, interpolate) { - return angular.isDefined(attribute) ? (interpolate ? $interpolate(attribute)($scope.$parent) : $scope.$parent.$eval(attribute)) : defaultValue; - }; + $scope.$watch('totalItems', function() { + $scope.totalPages = self.calculateTotalPages(); + }); + + $scope.$watch('totalPages', function(value) { + if ( $attrs.numPages ) { + $scope.numPages = value; // Readonly variable + } + + if ( self.page > value ) { + $scope.selectPage(value); + } else { + self.render(); + } + }); + + $scope.$watch('page', function() { + self.render(); + }); }]) .constant('paginationConfig', { + itemsPerPage: 10, boundaryLinks: false, directionLinks: true, firstText: 'First', @@ -1689,14 +1720,14 @@ angular.module('ui.bootstrap.pagination', []) rotate: true }) -.directive('pagination', ['paginationConfig', function(config) { +.directive('pagination', ['$parse', 'paginationConfig', function($parse, config) { return { restrict: 'EA', scope: { - numPages: '=', - currentPage: '=', - maxSize: '=', - onSelectPage: '&' + page: '=', + totalItems: '=', + onSelectPage:' &', + numPages: '=' }, controller: 'PaginationController', templateUrl: 'template/pagination/pagination.html', @@ -1704,13 +1735,23 @@ angular.module('ui.bootstrap.pagination', []) link: function(scope, element, attrs, paginationCtrl) { // Setup configuration parameters - var boundaryLinks = paginationCtrl.getAttributeValue(attrs.boundaryLinks, config.boundaryLinks ), - directionLinks = paginationCtrl.getAttributeValue(attrs.directionLinks, config.directionLinks ), - firstText = paginationCtrl.getAttributeValue(attrs.firstText, config.firstText, true), - previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true), - nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true), - lastText = paginationCtrl.getAttributeValue(attrs.lastText, config.lastText, true), - rotate = paginationCtrl.getAttributeValue(attrs.rotate, config.rotate); + var maxSize, + boundaryLinks = paginationCtrl.getAttributeValue(attrs.boundaryLinks, config.boundaryLinks ), + directionLinks = paginationCtrl.getAttributeValue(attrs.directionLinks, config.directionLinks ), + firstText = paginationCtrl.getAttributeValue(attrs.firstText, config.firstText, true), + previousText = paginationCtrl.getAttributeValue(attrs.previousText, config.previousText, true), + nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true), + lastText = paginationCtrl.getAttributeValue(attrs.lastText, config.lastText, true), + rotate = paginationCtrl.getAttributeValue(attrs.rotate, config.rotate); + + paginationCtrl.init(config.itemsPerPage); + + if (attrs.maxSize) { + scope.$parent.$watch($parse(attrs.maxSize), function(value) { + maxSize = parseInt(value, 10); + paginationCtrl.render(); + }); + } // Create page object used in template function makePage(number, text, isActive, isDisabled) { @@ -1722,76 +1763,79 @@ angular.module('ui.bootstrap.pagination', []) }; } - scope.$watch('numPages + currentPage + maxSize', function() { - paginationCtrl.reset(); + paginationCtrl.getPages = function(currentPage, totalPages) { + var pages = []; // Default page limits - var startPage = 1, endPage = scope.numPages; - var isMaxSized = ( angular.isDefined(scope.maxSize) && scope.maxSize < scope.numPages ); + var startPage = 1, endPage = totalPages; + var isMaxSized = ( angular.isDefined(maxSize) && maxSize < totalPages ); // recompute if maxSize if ( isMaxSized ) { if ( rotate ) { // Current page is displayed in the middle of the visible ones - startPage = Math.max(paginationCtrl.currentPage - Math.floor(scope.maxSize/2), 1); - endPage = startPage + scope.maxSize - 1; + startPage = Math.max(currentPage - Math.floor(maxSize/2), 1); + endPage = startPage + maxSize - 1; // Adjust if limit is exceeded - if (endPage > scope.numPages) { - endPage = scope.numPages; - startPage = endPage - scope.maxSize + 1; + if (endPage > totalPages) { + endPage = totalPages; + startPage = endPage - maxSize + 1; } } else { // Visible pages are paginated with maxSize - startPage = ((Math.ceil(paginationCtrl.currentPage / scope.maxSize) - 1) * scope.maxSize) + 1; + startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1; // Adjust last page if limit is exceeded - endPage = Math.min(startPage + scope.maxSize - 1, scope.numPages); + endPage = Math.min(startPage + maxSize - 1, totalPages); } } // Add page number links for (var number = startPage; number <= endPage; number++) { var page = makePage(number, number, paginationCtrl.isActive(number), false); - scope.pages.push(page); + pages.push(page); } // Add links to move between page sets if ( isMaxSized && ! rotate ) { if ( startPage > 1 ) { var previousPageSet = makePage(startPage - 1, '...', false, false); - scope.pages.unshift(previousPageSet); + pages.unshift(previousPageSet); } - if ( endPage < scope.numPages ) { + if ( endPage < totalPages ) { var nextPageSet = makePage(endPage + 1, '...', false, false); - scope.pages.push(nextPageSet); + pages.push(nextPageSet); } } // Add previous & next links if (directionLinks) { - var previousPage = makePage(paginationCtrl.currentPage - 1, previousText, false, paginationCtrl.noPrevious()); - scope.pages.unshift(previousPage); + var previousPage = makePage(currentPage - 1, previousText, false, paginationCtrl.noPrevious()); + pages.unshift(previousPage); - var nextPage = makePage(paginationCtrl.currentPage + 1, nextText, false, paginationCtrl.noNext()); - scope.pages.push(nextPage); + var nextPage = makePage(currentPage + 1, nextText, false, paginationCtrl.noNext()); + pages.push(nextPage); } // Add first & last links if (boundaryLinks) { var firstPage = makePage(1, firstText, false, paginationCtrl.noPrevious()); - scope.pages.unshift(firstPage); + pages.unshift(firstPage); - var lastPage = makePage(scope.numPages, lastText, false, paginationCtrl.noNext()); - scope.pages.push(lastPage); + var lastPage = makePage(totalPages, lastText, false, paginationCtrl.noNext()); + pages.push(lastPage); } - }); + + return pages; + }; } }; }]) .constant('pagerConfig', { + itemsPerPage: 10, previousText: '« Previous', nextText: 'Next »', align: true @@ -1801,9 +1845,10 @@ angular.module('ui.bootstrap.pagination', []) return { restrict: 'EA', scope: { - numPages: '=', - currentPage: '=', - onSelectPage: '&' + page: '=', + totalItems: '=', + onSelectPage:' &', + numPages: '=' }, controller: 'PaginationController', templateUrl: 'template/pagination/pager.html', @@ -1815,6 +1860,8 @@ angular.module('ui.bootstrap.pagination', []) nextText = paginationCtrl.getAttributeValue(attrs.nextText, config.nextText, true), align = paginationCtrl.getAttributeValue(attrs.align, config.align); + paginationCtrl.init(config.itemsPerPage); + // Create page object used in template function makePage(number, text, isDisabled, isPrevious, isNext) { return { @@ -1826,16 +1873,12 @@ angular.module('ui.bootstrap.pagination', []) }; } - scope.$watch('numPages + currentPage', function() { - paginationCtrl.reset(); - - // Add previous & next links - var previousPage = makePage(paginationCtrl.currentPage - 1, previousText, paginationCtrl.noPrevious(), true, false); - scope.pages.unshift(previousPage); - - var nextPage = makePage(paginationCtrl.currentPage + 1, nextText, paginationCtrl.noNext(), false, true); - scope.pages.push(nextPage); - }); + paginationCtrl.getPages = function(currentPage) { + return [ + makePage(currentPage - 1, previousText, paginationCtrl.noPrevious(), true, false), + makePage(currentPage + 1, nextText, paginationCtrl.noNext(), false, true) + ]; + }; } }; }]); @@ -1845,7 +1888,7 @@ angular.module('ui.bootstrap.pagination', []) * function, placement as a function, inside, support for more triggers than * just mouse enter/leave, html tooltips, and selector delegation. */ -angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position' ] ) +angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position', 'ui.bootstrap.bindHtml' ] ) /** * The $tooltip service creates tooltip- and popover-like directives as well as @@ -2026,13 +2069,6 @@ angular.module( 'ui.bootstrap.tooltip', [ 'ui.bootstrap.position' ] ) // Calculate the tooltip's top and left coordinates to center it with // this directive. switch ( scope.tt_placement ) { - case 'mouse': - var mousePos = $position.mouse(); - ttPosition = { - top: mousePos.y, - left: mousePos.x - }; - break; case 'right': ttPosition = { top: position.top + position.height / 2 - ttHeight / 2, @@ -2313,60 +2349,86 @@ angular.module('ui.bootstrap.progressbar', ['ui.bootstrap.transition']) angular.module('ui.bootstrap.rating', []) .constant('ratingConfig', { - max: 5 + max: 5, + stateOn: null, + stateOff: null }) -.directive('rating', ['ratingConfig', '$parse', function(ratingConfig, $parse) { - return { - restrict: 'EA', - scope: { - value: '=', - onHover: '&', - onLeave: '&' - }, - templateUrl: 'template/rating/rating.html', - replace: true, - link: function(scope, element, attrs) { +.controller('RatingController', ['$scope', '$attrs', '$parse', 'ratingConfig', function($scope, $attrs, $parse, ratingConfig) { - var maxRange = angular.isDefined(attrs.max) ? scope.$parent.$eval(attrs.max) : ratingConfig.max; + this.maxRange = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max; + this.stateOn = angular.isDefined($attrs.stateOn) ? $scope.$parent.$eval($attrs.stateOn) : ratingConfig.stateOn; + this.stateOff = angular.isDefined($attrs.stateOff) ? $scope.$parent.$eval($attrs.stateOff) : ratingConfig.stateOff; - scope.range = []; - for (var i = 1; i <= maxRange; i++) { - scope.range.push(i); - } + this.createDefaultRange = function(len) { + var defaultStateObject = { + stateOn: this.stateOn, + stateOff: this.stateOff + }; - scope.rate = function(value) { - if ( ! scope.readonly ) { - scope.value = value; - } - }; + var states = new Array(len); + for (var i = 0; i < len; i++) { + states[i] = defaultStateObject; + } + return states; + }; - scope.enter = function(value) { - if ( ! scope.readonly ) { - scope.val = value; - } - scope.onHover({value: value}); - }; + this.normalizeRange = function(states) { + for (var i = 0, n = states.length; i < n; i++) { + states[i].stateOn = states[i].stateOn || this.stateOn; + states[i].stateOff = states[i].stateOff || this.stateOff; + } + return states; + }; - scope.reset = function() { - scope.val = angular.copy(scope.value); - scope.onLeave(); - }; - scope.reset(); + // Get objects used in template + $scope.range = angular.isDefined($attrs.ratingStates) ? this.normalizeRange(angular.copy($scope.$parent.$eval($attrs.ratingStates))): this.createDefaultRange(this.maxRange); - scope.$watch('value', function(value) { - scope.val = value; - }); + $scope.rate = function(value) { + if ( $scope.readonly || $scope.value === value) { + return; + } - scope.readonly = false; - if (attrs.readonly) { - scope.$parent.$watch($parse(attrs.readonly), function(value) { - scope.readonly = !!value; - }); - } + $scope.value = value; + }; + + $scope.enter = function(value) { + if ( ! $scope.readonly ) { + $scope.val = value; } + $scope.onHover({value: value}); }; -}]); + + $scope.reset = function() { + $scope.val = angular.copy($scope.value); + $scope.onLeave(); + }; + + $scope.$watch('value', function(value) { + $scope.val = value; + }); + + $scope.readonly = false; + if ($attrs.readonly) { + $scope.$parent.$watch($parse($attrs.readonly), function(value) { + $scope.readonly = !!value; + }); + } +}]) + +.directive('rating', function() { + return { + restrict: 'EA', + scope: { + value: '=', + onHover: '&', + onLeave: '&' + }, + controller: 'RatingController', + templateUrl: 'template/rating/rating.html', + replace: true + }; +}); /** * @ngdoc overview @@ -2454,7 +2516,7 @@ function TabsetCtrl($scope, $element) { templateUrl: 'template/tabs/tabset.html', compile: function(elm, attrs, transclude) { return function(scope, element, attrs, tabsetCtrl) { - scope.vertical = angular.isDefined(attrs.vertical) ? scope.$eval(attrs.vertical) : false; + scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false; scope.type = angular.isDefined(attrs.type) ? scope.$parent.$eval(attrs.type) : 'tabs'; scope.direction = angular.isDefined(attrs.direction) ? scope.$parent.$eval(attrs.direction) : 'top'; scope.tabsAbove = (scope.direction != 'below'); @@ -2662,7 +2724,7 @@ function($parse, $http, $templateCache, $compile) { } }]) -.directive('tabsetTitles', function($http) { +.directive('tabsetTitles', ['$http', function($http) { return { restrict: 'A', require: '^tabset', @@ -2679,22 +2741,13 @@ function($parse, $http, $templateCache, $compile) { } } }; -}) +}]) ; angular.module('ui.bootstrap.timepicker', []) -.filter('pad', function() { - return function(input) { - if ( angular.isDefined(input) && input.toString().length < 2 ) { - input = '0' + input; - } - return input; - }; -}) - .constant('timepickerConfig', { hourStep: 1, minuteStep: 1, @@ -2704,16 +2757,18 @@ angular.module('ui.bootstrap.timepicker', []) mousewheel: true }) -.directive('timepicker', ['padFilter', '$parse', 'timepickerConfig', function (padFilter, $parse, timepickerConfig) { +.directive('timepicker', ['$parse', '$log', 'timepickerConfig', function ($parse, $log, timepickerConfig) { return { restrict: 'EA', - require:'ngModel', + require:'?^ngModel', replace: true, + scope: {}, templateUrl: 'template/timepicker/timepicker.html', - scope: { - model: '=ngModel' - }, - link: function(scope, element, attrs, ngModelCtrl) { + link: function(scope, element, attrs, ngModel) { + if ( !ngModel ) { + return; // do nothing if no ng-model + } + var selected = new Date(), meridians = timepickerConfig.meridians; var hourStep = timepickerConfig.hourStep; @@ -2734,28 +2789,27 @@ angular.module('ui.bootstrap.timepicker', []) scope.showMeridian = timepickerConfig.showMeridian; if (attrs.showMeridian) { scope.$parent.$watch($parse(attrs.showMeridian), function(value) { - scope.showMeridian = !! value; - - if ( ! scope.model ) { - // Reset - var dt = new Date( selected ); - var hours = getScopeHours(); - if (angular.isDefined( hours )) { - dt.setHours( hours ); + scope.showMeridian = !!value; + + if ( ngModel.$error.time ) { + // Evaluate from template + var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate(); + if (angular.isDefined( hours ) && angular.isDefined( minutes )) { + selected.setHours( hours ); + refresh(); } - scope.model = new Date( dt ); } else { - refreshTemplate(); + updateTemplate(); } }); } // Get scope.hours in 24H mode if valid - function getScopeHours ( ) { + function getHoursFromTemplate ( ) { var hours = parseInt( scope.hours, 10 ); var valid = ( scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24); if ( !valid ) { - return; + return undefined; } if ( scope.showMeridian ) { @@ -2769,14 +2823,22 @@ angular.module('ui.bootstrap.timepicker', []) return hours; } + function getMinutesFromTemplate() { + var minutes = parseInt(scope.minutes, 10); + return ( minutes >= 0 && minutes < 60 ) ? minutes : undefined; + } + + function pad( value ) { + return ( angular.isDefined(value) && value.toString().length < 2 ) ? '0' + value : value; + } + // Input elements - var inputs = element.find('input'); - var hoursInputEl = inputs.eq(0), minutesInputEl = inputs.eq(1); + var inputs = element.find('input'), hoursInputEl = inputs.eq(0), minutesInputEl = inputs.eq(1); // Respond on mousewheel spin var mousewheel = (angular.isDefined(attrs.mousewheel)) ? scope.$eval(attrs.mousewheel) : timepickerConfig.mousewheel; if ( mousewheel ) { - + var isScrollingUp = function(e) { if (e.originalEvent) { e = e.originalEvent; @@ -2785,7 +2847,7 @@ angular.module('ui.bootstrap.timepicker', []) var delta = (e.wheelDelta) ? e.wheelDelta : -e.deltaY; return (e.detail || delta > 0); }; - + hoursInputEl.bind('mousewheel wheel', function(e) { scope.$apply( (isScrollingUp(e)) ? scope.incrementHours() : scope.decrementHours() ); e.preventDefault(); @@ -2797,50 +2859,54 @@ angular.module('ui.bootstrap.timepicker', []) }); } - var keyboardChange = false; scope.readonlyInput = (angular.isDefined(attrs.readonlyInput)) ? scope.$eval(attrs.readonlyInput) : timepickerConfig.readonlyInput; if ( ! scope.readonlyInput ) { + + var invalidate = function(invalidHours, invalidMinutes) { + ngModel.$setViewValue( null ); + ngModel.$setValidity('time', false); + if (angular.isDefined(invalidHours)) { + scope.invalidHours = invalidHours; + } + if (angular.isDefined(invalidMinutes)) { + scope.invalidMinutes = invalidMinutes; + } + }; + scope.updateHours = function() { - var hours = getScopeHours(); + var hours = getHoursFromTemplate(); if ( angular.isDefined(hours) ) { - keyboardChange = 'h'; - if ( scope.model === null ) { - scope.model = new Date( selected ); - } - scope.model.setHours( hours ); + selected.setHours( hours ); + refresh( 'h' ); } else { - scope.model = null; - scope.validHours = false; + invalidate(true); } }; hoursInputEl.bind('blur', function(e) { - if ( scope.validHours && scope.hours < 10) { + if ( !scope.validHours && scope.hours < 10) { scope.$apply( function() { - scope.hours = padFilter( scope.hours ); + scope.hours = pad( scope.hours ); }); } }); scope.updateMinutes = function() { - var minutes = parseInt(scope.minutes, 10); - if ( minutes >= 0 && minutes < 60 ) { - keyboardChange = 'm'; - if ( scope.model === null ) { - scope.model = new Date( selected ); - } - scope.model.setMinutes( minutes ); + var minutes = getMinutesFromTemplate(); + + if ( angular.isDefined(minutes) ) { + selected.setMinutes( minutes ); + refresh( 'm' ); } else { - scope.model = null; - scope.validMinutes = false; + invalidate(undefined, true); } }; minutesInputEl.bind('blur', function(e) { - if ( scope.validMinutes && scope.minutes < 10 ) { + if ( !scope.invalidMinutes && scope.minutes < 10 ) { scope.$apply( function() { - scope.minutes = padFilter( scope.minutes ); + scope.minutes = pad( scope.minutes ); }); } }); @@ -2849,38 +2915,49 @@ angular.module('ui.bootstrap.timepicker', []) scope.updateMinutes = angular.noop; } - scope.$watch( function getModelTimestamp() { - return +scope.model; - }, function( timestamp ) { - if ( !isNaN( timestamp ) && timestamp > 0 ) { - selected = new Date( timestamp ); - refreshTemplate(); - } - }); + ngModel.$render = function() { + var date = ngModel.$modelValue ? new Date( ngModel.$modelValue ) : null; - function refreshTemplate() { - var hours = selected.getHours(); - if ( scope.showMeridian ) { - // Convert 24 to 12 hour system - hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; + if ( isNaN(date) ) { + ngModel.$setValidity('time', false); + $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.'); + } else { + if ( date ) { + selected = date; + } + makeValid(); + updateTemplate(); } - scope.hours = ( keyboardChange === 'h' ) ? hours : padFilter(hours); - scope.validHours = true; + }; + + // Call internally when we know that model is valid. + function refresh( keyboardChange ) { + makeValid(); + ngModel.$setViewValue( new Date(selected) ); + updateTemplate( keyboardChange ); + } - var minutes = selected.getMinutes(); - scope.minutes = ( keyboardChange === 'm' ) ? minutes : padFilter(minutes); - scope.validMinutes = true; + function makeValid() { + ngModel.$setValidity('time', true); + scope.invalidHours = false; + scope.invalidMinutes = false; + } - scope.meridian = ( scope.showMeridian ) ? (( selected.getHours() < 12 ) ? meridians[0] : meridians[1]) : ''; + function updateTemplate( keyboardChange ) { + var hours = selected.getHours(), minutes = selected.getMinutes(); - keyboardChange = false; + if ( scope.showMeridian ) { + hours = ( hours === 0 || hours === 12 ) ? 12 : hours % 12; // Convert 24 to 12 hour system + } + scope.hours = keyboardChange === 'h' ? hours : pad(hours); + scope.minutes = keyboardChange === 'm' ? minutes : pad(minutes); + scope.meridian = selected.getHours() < 12 ? meridians[0] : meridians[1]; } function addMinutes( minutes ) { var dt = new Date( selected.getTime() + minutes * 60000 ); - selected.setHours( dt.getHours() ); - selected.setMinutes( dt.getMinutes() ); - scope.model = new Date( selected ); + selected.setHours( dt.getHours(), dt.getMinutes() ); + refresh(); } scope.incrementHours = function() { @@ -2902,7 +2979,7 @@ angular.module('ui.bootstrap.timepicker', []) }; }]); -angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) +angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml']) /** * A helper service that can parse typeahead's syntax (string provided by users) @@ -2933,7 +3010,8 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) }; }]) - .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser', function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) { + .directive('typeahead', ['$compile', '$parse', '$q', '$timeout', '$document', '$position', 'typeaheadParser', + function ($compile, $parse, $q, $timeout, $document, $position, typeaheadParser) { var HOT_KEYS = [9, 13, 27, 38, 40]; @@ -3046,7 +3124,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) //plug into $parsers pipeline to open a typeahead on view changes initiated from DOM //$parsers kick-in on all the changes coming from the view as well as manually triggered by $setViewValue - modelCtrl.$parsers.push(function (inputValue) { + modelCtrl.$parsers.unshift(function (inputValue) { resetMatches(); if (inputValue && inputValue.length >= minSearch) { @@ -3062,7 +3140,12 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) } } - return isEditable ? inputValue : undefined; + if (isEditable) { + return inputValue; + } else { + modelCtrl.$setValidity('editable', false); + return undefined; + } }); modelCtrl.$formatters.push(function (modelValue) { @@ -3076,12 +3159,13 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) return inputFormatter(originalScope, locals); } else { - locals[parserResult.itemName] = modelValue; //it might happen that we don't have enough info to properly render input value //we need to check for this situation and simply return model value if we can't apply custom formatting + locals[parserResult.itemName] = modelValue; candidateViewValue = parserResult.viewMapper(originalScope, locals); - emptyViewValue = parserResult.viewMapper(originalScope, {}); + locals[parserResult.itemName] = undefined; + emptyViewValue = parserResult.viewMapper(originalScope, locals); return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue; } @@ -3095,6 +3179,7 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) locals[parserResult.itemName] = item = scope.matches[activeIdx].model; model = parserResult.modelMapper(originalScope, locals); $setModelValue(originalScope, model); + modelCtrl.$setValidity('editable', true); onSelectCallback(originalScope, { $item: item, @@ -3102,8 +3187,9 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) $label: parserResult.viewMapper(originalScope, locals) }); - //return focus to the input element if a mach was selected via a mouse click event resetMatches(); + + //return focus to the input element if a mach was selected via a mouse click event element[0].focus(); }; @@ -3138,9 +3224,18 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) } }); - $document.bind('click', function(){ - resetMatches(); - scope.$digest(); + // Keep reference to click handler to unbind it. + var dismissClickHandler = function (evt) { + if (element[0] !== evt.target) { + resetMatches(); + scope.$digest(); + } + }; + + $document.bind('click', dismissClickHandler); + + originalScope.$on('$destroy', function(){ + $document.unbind('click', dismissClickHandler); }); element.after($compile(popUpEl)(scope)); @@ -3208,6 +3303,6 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) } return function(matchItem, query) { - return query ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : query; + return query ? matchItem.replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; }; }); \ No newline at end of file diff --git a/ui-bootstrap.min.js b/ui-bootstrap.min.js index 7708914..559090f 100644 --- a/ui-bootstrap.min.js +++ b/ui-bootstrap.min.js @@ -1,2 +1,2 @@ -angular.module("ui.bootstrap",["ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dialog","ui.bootstrap.dropdownToggle","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"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(e,t,n){function a(e){for(var t in e)if(void 0!==o.style[t])return e[t]}var i=function(a,o,r){r=r||{};var l=e.defer(),s=i[r.animation?"animationEndEventName":"transitionEndEventName"],c=function(){n.$apply(function(){a.unbind(s,c),l.resolve(a)})};return s&&a.bind(s,c),t(function(){angular.isString(o)?a.addClass(o):angular.isFunction(o)?o(a):angular.isObject(o)&&a.css(o),s||l.resolve(a)}),l.promise.cancel=function(){s&&a.unbind(s,c),l.reject("Transition cancelled")},l.promise},o=document.createElement("trans"),r={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},l={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return i.transitionEndEventName=a(r),i.animationEndEventName=a(l),i}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(e){var t=function(e,t,n){t.removeClass("collapse"),t.css({height:n}),t[0].offsetWidth,t.addClass("collapse")};return{link:function(n,a,i){var o,r=!0;n.$watch(function(){return a[0].scrollHeight},function(){0!==a[0].scrollHeight&&(o||(r?t(n,a,a[0].scrollHeight+"px"):t(n,a,"auto")))}),n.$watch(i.collapse,function(e){e?u():c()});var l,s=function(t){return l&&l.cancel(),l=e(a,t),l.then(function(){l=void 0},function(){l=void 0}),l},c=function(){r?(r=!1,o||t(n,a,"auto")):s({height:a[0].scrollHeight+"px"}).then(function(){o||t(n,a,"auto")}),o=!1},u=function(){o=!0,r?(r=!1,t(n,a,0)):(t(n,a,a[0].scrollHeight+"px"),s({height:"0"}))}}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(e,t,n){this.groups=[],this.closeOthers=function(a){var i=angular.isDefined(t.closeOthers)?e.$eval(t.closeOthers):n.closeOthers;i&&angular.forEach(this.groups,function(e){e!==a&&(e.isOpen=!1)})},this.addGroup=function(e){var t=this;this.groups.push(e),e.$on("$destroy",function(){t.removeGroup(e)})},this.removeGroup=function(e){var t=this.groups.indexOf(e);-1!==t&&this.groups.splice(this.groups.indexOf(e),1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",["$parse","$transition","$timeout",function(e){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@"},controller:["$scope",function(){this.setHeading=function(e){this.heading=e}}],link:function(t,n,a,i){var o,r;i.addGroup(t),t.isOpen=!1,a.isOpen&&(o=e(a.isOpen),r=o.assign,t.$watch(function(){return o(t.$parent)},function(e){t.isOpen=e}),t.isOpen=o?o(t.$parent):!1),t.$watch("isOpen",function(e){e&&i.closeOthers(t),r&&r(t.$parent,e)})}}}]).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",compile:function(e,t,n){return function(e,t,a,i){i.setHeading(n(e,function(){}))}}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(e,t,n,a){e.$watch(function(){return a[n.accordionTransclude]},function(e){e&&(t.html(""),t.append(e))})}}}),angular.module("ui.bootstrap.alert",[]).directive("alert",function(){return{restrict:"EA",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"=",close:"&"},link:function(e,t,n){e.closeable="close"in n}}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).directive("btnRadio",["buttonConfig",function(e){var t=e.activeClass||"active",n=e.toggleEvent||"click";return{require:"ngModel",link:function(e,a,i,o){o.$render=function(){a.toggleClass(t,angular.equals(o.$modelValue,e.$eval(i.btnRadio)))},a.bind(n,function(){a.hasClass(t)||e.$apply(function(){o.$setViewValue(e.$eval(i.btnRadio)),o.$render()})})}}}]).directive("btnCheckbox",["buttonConfig",function(e){var t=e.activeClass||"active",n=e.toggleEvent||"click";return{require:"ngModel",link:function(e,a,i,o){function r(){var t=e.$eval(i.btnCheckboxTrue);return angular.isDefined(t)?t:!0}function l(){var t=e.$eval(i.btnCheckboxFalse);return angular.isDefined(t)?t:!1}o.$render=function(){a.toggleClass(t,angular.equals(o.$modelValue,r()))},a.bind(n,function(){e.$apply(function(){o.$setViewValue(a.hasClass(t)?l():r()),o.$render()})})}}}]),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$transition","$q",function(e,t,n){function a(){function n(){o?(e.next(),a()):e.pause()}i&&t.cancel(i);var r=+e.interval;!isNaN(r)&&r>=0&&(i=t(n,r))}var i,o,r=this,l=r.slides=[],s=-1;r.currentSlide=null,r.select=function(i,o){function c(){r.currentSlide&&angular.isString(o)&&!e.noTransition&&i.$element?(i.$element.addClass(o),i.$element[0].offsetWidth=i.$element[0].offsetWidth,angular.forEach(l,function(e){angular.extend(e,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(i,{direction:o,active:!0,entering:!0}),angular.extend(r.currentSlide||{},{direction:o,leaving:!0}),e.$currentTransition=n(i.$element,{}),function(t,n){e.$currentTransition.then(function(){u(t,n)},function(){u(t,n)})}(i,r.currentSlide)):u(i,r.currentSlide),r.currentSlide=i,s=p,a()}function u(t,n){angular.extend(t,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(n||{},{direction:"",active:!1,leaving:!1,entering:!1}),e.$currentTransition=null}var p=l.indexOf(i);void 0===o&&(o=p>s?"next":"prev"),i&&i!==r.currentSlide&&(e.$currentTransition?(e.$currentTransition.cancel(),t(c)):c())},r.indexOfSlide=function(e){return l.indexOf(e)},e.next=function(){var t=(s+1)%l.length;return e.$currentTransition?void 0:r.select(l[t],"next")},e.prev=function(){var t=0>s-1?l.length-1:s-1;return e.$currentTransition?void 0:r.select(l[t],"prev")},e.select=function(e){r.select(e)},e.isActive=function(e){return r.currentSlide===e},e.slides=function(){return l},e.$watch("interval",a),e.play=function(){o||(o=!0,a())},e.pause=function(){e.noPause||(o=!1,i&&t.cancel(i))},r.addSlide=function(t,n){t.$element=n,l.push(t),1===l.length||t.active?(r.select(l[l.length-1]),1==l.length&&e.play()):t.active=!1},r.removeSlide=function(e){var t=l.indexOf(e);l.splice(t,1),l.length>0&&e.active?t>=l.length?r.select(l[t-1]):r.select(l[t]):s>t&&s--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",["$parse",function(e){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{},link:function(t,n,a,i){if(a.active){var o=e(a.active),r=o.assign,l=t.active=o(t.$parent);t.$watch(function(){var e=o(t.$parent);return e!==t.active&&(e!==l?l=t.active=e:r(t.$parent,e=l=t.active)),e})}i.addSlide(t,n),t.$on("$destroy",function(){i.removeSlide(t)}),t.$watch("active",function(e){e&&i.select(t)})}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(e,t){function n(e,n){return e.currentStyle?e.currentStyle[n]:t.getComputedStyle?t.getComputedStyle(e)[n]:e.style[n]}function a(e){return"static"===(n(e,"position")||"static")}var i,o;e.bind("mousemove",function(e){i=e.pageX,o=e.pageY});var r=function(t){for(var n=e[0],i=t.offsetParent||n;i&&i!==n&&a(i);)i=i.offsetParent;return i||n};return{position:function(t){var n=this.offset(t),a={top:0,left:0},i=r(t[0]);return i!=e[0]&&(a=this.offset(angular.element(i)),a.top+=i.clientTop-i.scrollTop,a.left+=i.clientLeft-i.scrollLeft),{width:t.prop("offsetWidth"),height:t.prop("offsetHeight"),top:n.top-a.top,left:n.left-a.left}},offset:function(n){var a=n[0].getBoundingClientRect();return{width:n.prop("offsetWidth"),height:n.prop("offsetHeight"),top:a.top+(t.pageYOffset||e[0].body.scrollTop),left:a.left+(t.pageXOffset||e[0].body.scrollLeft)}},mouse:function(){return{x:i,y:o}}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.position"]).constant("datepickerConfig",{dayFormat:"dd",monthFormat:"MMMM",yearFormat:"yyyy",dayHeaderFormat:"EEE",dayTitleFormat:"MMMM yyyy",monthTitleFormat:"yyyy",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","dateFilter","datepickerConfig",function(e,t,n,a){function i(t,n){return angular.isDefined(t)?e.$parent.$eval(t):n}function o(e,t){return new Date(e,t,0).getDate()}function r(e,t){for(var n=Array(t),a=e,i=0;t>i;)n[i++]=new Date(a),a.setDate(a.getDate()+1);return n}function l(e,t,a,i){return{date:e,label:n(e,t),selected:!!a,secondary:!!i}}var s={day:i(t.dayFormat,a.dayFormat),month:i(t.monthFormat,a.monthFormat),year:i(t.yearFormat,a.yearFormat),dayHeader:i(t.dayHeaderFormat,a.dayHeaderFormat),dayTitle:i(t.dayTitleFormat,a.dayTitleFormat),monthTitle:i(t.monthTitleFormat,a.monthTitleFormat)},c=i(t.startingDay,a.startingDay),u=i(t.yearRange,a.yearRange);this.minDate=a.minDate?new Date(a.minDate):null,this.maxDate=a.maxDate?new Date(a.maxDate):null,this.modes=[{name:"day",getVisibleDates:function(e,t){var a=e.getFullYear(),i=e.getMonth(),u=new Date(a,i,1),p=c-u.getDay(),d=p>0?7-p:-p,f=new Date(u),m=0;d>0&&(f.setDate(-d+1),m+=d),m+=o(a,i+1),m+=(7-m%7)%7;for(var g=r(f,m),h=Array(7),v=0;m>v;v++){var b=new Date(g[v]);g[v]=l(b,s.day,t&&t.getDate()===b.getDate()&&t.getMonth()===b.getMonth()&&t.getFullYear()===b.getFullYear(),b.getMonth()!==i)}for(var $=0;7>$;$++)h[$]=n(g[$].date,s.dayHeader);return{objects:g,title:n(e,s.dayTitle),labels:h}},compare:function(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate())-new Date(t.getFullYear(),t.getMonth(),t.getDate())},split:7,step:{months:1}},{name:"month",getVisibleDates:function(e,t){for(var a=Array(12),i=e.getFullYear(),o=0;12>o;o++){var r=new Date(i,o,1);a[o]=l(r,s.month,t&&t.getMonth()===o&&t.getFullYear()===i)}return{objects:a,title:n(e,s.monthTitle)}},compare:function(e,t){return new Date(e.getFullYear(),e.getMonth())-new Date(t.getFullYear(),t.getMonth())},split:3,step:{years:1}},{name:"year",getVisibleDates:function(e,t){for(var n=Array(u),a=e.getFullYear(),i=parseInt((a-1)/u,10)*u+1,o=0;u>o;o++){var r=new Date(i+o,0,1);n[o]=l(r,s.year,t&&t.getFullYear()===r.getFullYear())}return{objects:n,title:[n[0].label,n[u-1].label].join(" - ")}},compare:function(e,t){return e.getFullYear()-t.getFullYear()},split:5,step:{years:u}}],this.isDisabled=function(t,n){var a=this.modes[n||0];return this.minDate&&0>a.compare(t,this.minDate)||this.maxDate&&a.compare(t,this.maxDate)>0||e.dateDisabled&&e.dateDisabled({date:t,mode:a.name})}}]).directive("datepicker",["dateFilter","$parse","datepickerConfig","$log",function(e,t,n,a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(e,i,o,r){function l(){e.showWeekNumbers=0===m&&h}function s(e,t){for(var n=[];e.length>0;)n.push(e.splice(0,t));return n}function c(t){var n=null,i=!0;f.$modelValue&&(n=new Date(f.$modelValue),isNaN(n)?(i=!1,a.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.')):t&&(g=n)),f.$setValidity("date",i);var o=d.modes[m],r=o.getVisibleDates(g,n);angular.forEach(r.objects,function(e){e.disabled=d.isDisabled(e.date,m)}),f.$setValidity("date-disabled",!n||!d.isDisabled(n)),e.rows=s(r.objects,o.split),e.labels=r.labels||[],e.title=r.title}function u(e){m=e,l(),c()}function p(e){var t=new Date(e);t.setDate(t.getDate()+4-(t.getDay()||7));var n=t.getTime();return t.setMonth(0),t.setDate(1),Math.floor(Math.round((n-t)/864e5)/7)+1}var d=r[0],f=r[1];if(f){var m=0,g=new Date,h=n.showWeeks;o.showWeeks?e.$parent.$watch(t(o.showWeeks),function(e){h=!!e,l()}):l(),o.min&&e.$parent.$watch(t(o.min),function(e){d.minDate=e?new Date(e):null,c()}),o.max&&e.$parent.$watch(t(o.max),function(e){d.maxDate=e?new Date(e):null,c()}),f.$render=function(){c(!0)},e.select=function(e){if(0===m){var t=new Date(f.$modelValue);t.setFullYear(e.getFullYear(),e.getMonth(),e.getDate()),f.$setViewValue(t),c(!0)}else g=e,u(m-1)},e.move=function(e){var t=d.modes[m].step;g.setMonth(g.getMonth()+e*(t.months||0)),g.setFullYear(g.getFullYear()+e*(t.years||0)),c()},e.toggleMode=function(){u((m+1)%d.modes.length)},e.getWeekNumber=function(t){return 0===m&&e.showWeekNumbers&&7===t.length?p(t[0].date):null}}}}}]).constant("datepickerPopupConfig",{dateFormat:"yyyy-MM-dd",closeOnDateSelection:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","datepickerPopupConfig",function(e,t,n,a,i,o){return{restrict:"EA",require:"ngModel",link:function(r,l,s,c){function u(e){return e?i(e,h):null}function p(e){if(e){var t=new Date(e);if(!isNaN(t))return t}return e}function d(e){$?$(r,!!e):v.isOpen=!!e}function f(e,n,a){e&&(r.$watch(t(e),function(e){v[n]=e}),D.attr(a||n,n))}function m(){v.position=a.position(l),v.position.top=v.position.top+l.prop("offsetHeight")}var g=angular.isDefined(s.closeOnDateSelection)?v.$eval(s.closeOnDateSelection):o.closeOnDateSelection,h=s.datepickerPopup||o.dateFormat,v=r.$new();r.$on("$destroy",function(){v.$destroy()}),c.$formatters.push(u),c.$parsers.push(p);var b,$;s.open&&(b=t(s.open),$=b.assign,r.$watch(b,function(e){v.isOpen=!!e})),v.isOpen=b?b(r):!1;var y=function(e){v.isOpen&&e.target!==l[0]&&v.$apply(function(){d(!1)})},w=function(){v.$apply(function(){d(!0)})},k=angular.element("");k.attr({"ng-model":"date","ng-change":"dateSelection()"});var D=k.find("datepicker");s.datepickerOptions&&D.attr(angular.extend({},r.$eval(s.datepickerOptions)));var x=t(s.ngModel).assign;v.dateSelection=function(){x(r,v.date),g&&d(!1)},v.$watch(function(){return c.$modelValue},function(e){if(angular.isString(e)){var t=p(e);if(e&&!t)throw x(r,null),Error(e+" cannot be parsed to a date object.");e=t}v.date=e,m()}),f(s.min,"min"),f(s.max,"max"),s.showWeeks?f(s.showWeeks,"showWeeks","show-weeks"):(v.showWeeks=!0,D.attr("show-weeks","showWeeks")),s.dateDisabled&&D.attr("date-disabled",s.dateDisabled),v.$watch("isOpen",function(e){e?(m(),n.bind("click",y),l.unbind("focus",w),l.focus()):(n.unbind("click",y),l.bind("focus",w)),$&&$(r,e)}),v.today=function(){x(r,new Date)},v.clear=function(){x(r,null)},l.after(e(k)(v))}}}]).directive("datepickerPopupWrap",[function(){return{restrict:"E",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(e,t){t.bind("click",function(e){e.preventDefault(),e.stopPropagation()})}}}]);var dialogModule=angular.module("ui.bootstrap.dialog",["ui.bootstrap.transition"]);dialogModule.controller("MessageBoxController",["$scope","dialog","model",function(e,t,n){e.title=n.title,e.message=n.message,e.buttons=n.buttons,e.close=function(e){t.close(e)}}]),dialogModule.provider("$dialog",function(){var e={backdrop:!0,dialogClass:"modal",backdropClass:"modal-backdrop",transitionClass:"fade",triggerClass:"in",resolve:{},backdropFade:!1,dialogFade:!1,keyboard:!0,backdropClick:!0},t={},n={value:0};this.options=function(e){t=e},this.$get=["$http","$document","$compile","$rootScope","$controller","$templateCache","$q","$transition","$injector",function(a,i,o,r,l,s,c,u,p){function d(e){var t=angular.element("
    ");return t.addClass(e),t}function f(n){var a=this,i=this.options=angular.extend({},e,t,n);this._open=!1,this.backdropEl=d(i.backdropClass),i.backdropFade&&(this.backdropEl.addClass(i.transitionClass),this.backdropEl.removeClass(i.triggerClass)),this.modalEl=d(i.dialogClass),i.dialogFade&&(this.modalEl.addClass(i.transitionClass),this.modalEl.removeClass(i.triggerClass)),this.handledEscapeKey=function(e){27===e.which&&(a.close(),e.preventDefault(),a.$scope.$apply())},this.handleBackDropClick=function(e){a.close(),e.preventDefault(),a.$scope.$apply()}}var m=i.find("body");return f.prototype.isOpen=function(){return this._open},f.prototype.open=function(e,t){var n=this,a=this.options;if(e&&(a.templateUrl=e),t&&(a.controller=t),!a.template&&!a.templateUrl)throw Error("Dialog.open expected template or templateUrl, neither found. Use options or open method to specify them.");return this._loadResolves().then(function(e){var t=e.$scope=n.$scope=e.$scope?e.$scope:r.$new();if(n.modalEl.html(e.$template),n.options.controller){var a=l(n.options.controller,e);n.modalEl.children().data("ngControllerController",a)}o(n.modalEl)(t),n._addElementsToDom(),setTimeout(function(){n.options.dialogFade&&n.modalEl.addClass(n.options.triggerClass),n.options.backdropFade&&n.backdropEl.addClass(n.options.triggerClass)}),n._bindEvents()}),this.deferred=c.defer(),this.deferred.promise},f.prototype.close=function(e){function t(e){e.removeClass(a.options.triggerClass)}function n(){a._open&&a._onCloseComplete(e)}var a=this,i=this._getFadingElements();if(i.length>0)for(var o=i.length-1;o>=0;o--)u(i[o],t).then(n);else this._onCloseComplete(e)},f.prototype._getFadingElements=function(){var e=[];return this.options.dialogFade&&e.push(this.modalEl),this.options.backdropFade&&e.push(this.backdropEl),e},f.prototype._bindEvents=function(){this.options.keyboard&&m.bind("keydown",this.handledEscapeKey),this.options.backdrop&&this.options.backdropClick&&this.backdropEl.bind("click",this.handleBackDropClick)},f.prototype._unbindEvents=function(){this.options.keyboard&&m.unbind("keydown",this.handledEscapeKey),this.options.backdrop&&this.options.backdropClick&&this.backdropEl.unbind("click",this.handleBackDropClick)},f.prototype._onCloseComplete=function(e){this._removeElementsFromDom(),this._unbindEvents(),this.deferred.resolve(e)},f.prototype._addElementsToDom=function(){m.append(this.modalEl),this.options.backdrop&&(0===n.value&&m.append(this.backdropEl),n.value++),this._open=!0},f.prototype._removeElementsFromDom=function(){this.modalEl.remove(),this.options.backdrop&&(n.value--,0===n.value&&this.backdropEl.remove()),this._open=!1},f.prototype._loadResolves=function(){var e,t=[],n=[],i=this;return this.options.template?e=c.when(this.options.template):this.options.templateUrl&&(e=a.get(this.options.templateUrl,{cache:s}).then(function(e){return e.data})),angular.forEach(this.options.resolve||[],function(e,a){n.push(a),t.push(angular.isString(e)?p.get(e):p.invoke(e))}),n.push("$template"),t.push(e),c.all(t).then(function(e){var t={};return angular.forEach(e,function(e,a){t[n[a]]=e}),t.dialog=i,t})},{dialog:function(e){return new f(e)},messageBox:function(e,t,n){return new f({templateUrl:"template/dialog/message.html",controller:"MessageBoxController",resolve:{model:function(){return{title:e,message:t,buttons:n}}}})}}}]}),angular.module("ui.bootstrap.dropdownToggle",[]).directive("dropdownToggle",["$document","$location",function(e){var t=null,n=angular.noop;return{restrict:"CA",link:function(a,i){a.$watch("$location.path",function(){n()}),i.parent().bind("click",function(){n()}),i.bind("click",function(a){var o=i===t;a.preventDefault(),a.stopPropagation(),t&&n(),o||(i.parent().addClass("open"),t=i,n=function(a){a&&(a.preventDefault(),a.stopPropagation()),e.unbind("click",n),i.parent().removeClass("open"),n=angular.noop,t=null},e.bind("click",n))})}}}]),angular.module("ui.bootstrap.modal",["ui.bootstrap.dialog"]).directive("modal",["$parse","$dialog",function(e,t){return{restrict:"EA",terminal:!0,link:function(n,a,i){var o,r=angular.extend({},n.$eval(i.uiOptions||i.bsOptions||i.options)),l=i.modal||i.show;r=angular.extend(r,{template:a.html(),resolve:{$scope:function(){return n}}});var s=t.dialog(r);a.remove(),o=i.close?function(){e(i.close)(n)}:function(){angular.isFunction(e(l).assign)&&e(l).assign(n,!1)},n.$watch(l,function(e){e?s.open().then(function(){o()}):s.isOpen()&&s.close()})}}}]),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$interpolate",function(e,t){this.currentPage=1,this.noPrevious=function(){return 1===this.currentPage},this.noNext=function(){return this.currentPage===e.numPages},this.isActive=function(e){return this.currentPage===e},this.reset=function(){e.pages=[],this.currentPage=parseInt(e.currentPage,10),this.currentPage>e.numPages&&e.selectPage(e.numPages)};var n=this;e.selectPage=function(t){!n.isActive(t)&&t>0&&e.numPages>=t&&(e.currentPage=t,e.onSelectPage({page:t}))},this.getAttributeValue=function(n,a,i){return angular.isDefined(n)?i?t(n)(e.$parent):e.$parent.$eval(n):a}}]).constant("paginationConfig",{boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["paginationConfig",function(e){return{restrict:"EA",scope:{numPages:"=",currentPage:"=",maxSize:"=",onSelectPage:"&"},controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(t,n,a,i){function o(e,t,n,a){return{number:e,text:t,active:n,disabled:a}}var r=i.getAttributeValue(a.boundaryLinks,e.boundaryLinks),l=i.getAttributeValue(a.directionLinks,e.directionLinks),s=i.getAttributeValue(a.firstText,e.firstText,!0),c=i.getAttributeValue(a.previousText,e.previousText,!0),u=i.getAttributeValue(a.nextText,e.nextText,!0),p=i.getAttributeValue(a.lastText,e.lastText,!0),d=i.getAttributeValue(a.rotate,e.rotate);t.$watch("numPages + currentPage + maxSize",function(){i.reset();var e=1,n=t.numPages,a=angular.isDefined(t.maxSize)&&t.maxSizet.numPages&&(n=t.numPages,e=n-t.maxSize+1)):(e=(Math.ceil(i.currentPage/t.maxSize)-1)*t.maxSize+1,n=Math.min(e+t.maxSize-1,t.numPages)));for(var f=e;n>=f;f++){var m=o(f,f,i.isActive(f),!1);t.pages.push(m)}if(a&&!d){if(e>1){var g=o(e-1,"...",!1,!1);t.pages.unshift(g)}if(t.numPages>n){var h=o(n+1,"...",!1,!1);t.pages.push(h)}}if(l){var v=o(i.currentPage-1,c,!1,i.noPrevious());t.pages.unshift(v);var b=o(i.currentPage+1,u,!1,i.noNext());t.pages.push(b)}if(r){var $=o(1,s,!1,i.noPrevious());t.pages.unshift($);var y=o(t.numPages,p,!1,i.noNext());t.pages.push(y)}})}}}]).constant("pagerConfig",{previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(e){return{restrict:"EA",scope:{numPages:"=",currentPage:"=",onSelectPage:"&"},controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(t,n,a,i){function o(e,t,n,a,i){return{number:e,text:t,disabled:n,previous:s&&a,next:s&&i}}var r=i.getAttributeValue(a.previousText,e.previousText,!0),l=i.getAttributeValue(a.nextText,e.nextText,!0),s=i.getAttributeValue(a.align,e.align);t.$watch("numPages + currentPage",function(){i.reset();var e=o(i.currentPage-1,r,i.noPrevious(),!0,!1);t.pages.unshift(e);var n=o(i.currentPage+1,l,i.noNext(),!1,!0);t.pages.push(n)})}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position"]).provider("$tooltip",function(){function e(e){var t=/[A-Z]/g,n="-";return e.replace(t,function(e,t){return(t?n:"")+e.toLowerCase()})}var t={placement:"top",animation:!0,popupDelay:0},n={mouseenter:"mouseleave",click:"click",focus:"blur"},a={};this.options=function(e){angular.extend(a,e)},this.setTriggers=function(e){angular.extend(n,e)},this.$get=["$window","$compile","$timeout","$parse","$document","$position","$interpolate",function(i,o,r,l,s,c,u){return function(i,p,d){function f(e){var t=e||m.trigger||d,a=n[t]||t;return{show:t,hide:a}}var m=angular.extend({},t,a),g=e(i),h=u.startSymbol(),v=u.endSymbol(),b="<"+g+"-popup "+'title="'+h+"tt_title"+v+'" '+'content="'+h+"tt_content"+v+'" '+'placement="'+h+"tt_placement"+v+'" '+'animation="tt_animation()" '+'is-open="tt_isOpen"'+">"+"";return{restrict:"EA",scope:!0,link:function(e,t,n){function a(){e.tt_isOpen?d():u()}function u(){e.tt_popupDelay?$=r(g,e.tt_popupDelay):e.$apply(g)}function d(){e.$apply(function(){h()})}function g(){var n,a,i,o;if(e.tt_content){switch(v&&r.cancel(v),w.css({top:0,left:0,display:"block"}),k?(y=y||s.find("body"),y.append(w)):t.after(w),n=k?c.offset(t):c.position(t),a=w.prop("offsetWidth"),i=w.prop("offsetHeight"),e.tt_placement){case"mouse":var l=c.mouse();o={top:l.y,left:l.x};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width};break;case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-a/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-a};break;default:o={top:n.top-i,left:n.left+n.width/2-a/2}}o.top+="px",o.left+="px",w.css(o),e.tt_isOpen=!0}}function h(){e.tt_isOpen=!1,r.cancel($),angular.isDefined(e.tt_animation)&&e.tt_animation()?v=r(function(){w.remove()},500):w.remove()}var v,$,y,w=o(b)(e),k=angular.isDefined(m.appendToBody)?m.appendToBody:!1,D=f(void 0),x=!1;e.tt_isOpen=!1,n.$observe(i,function(t){e.tt_content=t}),n.$observe(p+"Title",function(t){e.tt_title=t}),n.$observe(p+"Placement",function(t){e.tt_placement=angular.isDefined(t)?t:m.placement}),n.$observe(p+"Animation",function(t){e.tt_animation=angular.isDefined(t)?l(t):function(){return m.animation}}),n.$observe(p+"PopupDelay",function(t){var n=parseInt(t,10);e.tt_popupDelay=isNaN(n)?m.popupDelay:n}),n.$observe(p+"Trigger",function(e){x&&(t.unbind(D.show,u),t.unbind(D.hide,d)),D=f(e),D.show===D.hide?t.bind(D.show,a):(t.bind(D.show,u),t.bind(D.hide,d)),x=!0}),n.$observe(p+"AppendToBody",function(t){k=angular.isDefined(t)?l(t)(e):k}),k&&e.$on("$locationChangeSuccess",function(){e.tt_isOpen&&h()}),e.$on("$destroy",function(){e.tt_isOpen?h():w.remove()})}}}}]}).directive("tooltipPopup",function(){return{restrict:"E",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(e){return e("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"E",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(e){return e("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$compile","$timeout","$parse","$window","$tooltip",function(e,t,n,a,i){return i("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",["ui.bootstrap.transition"]).constant("progressConfig",{animate:!0,autoType:!1,stackedTypes:["success","info","warning","danger"]}).controller("ProgressBarController",["$scope","$attrs","progressConfig",function(e,t,n){function a(e){return r[e]}var i=angular.isDefined(t.animate)?e.$eval(t.animate):n.animate,o=angular.isDefined(t.autoType)?e.$eval(t.autoType):n.autoType,r=angular.isDefined(t.stackedTypes)?e.$eval("["+t.stackedTypes+"]"):n.stackedTypes;this.makeBar=function(e,t,n){var r=angular.isObject(e)?e.value:e||0,l=angular.isObject(t)?t.value:t||0,s=angular.isObject(e)&&angular.isDefined(e.type)?e.type:o?a(n||0):null;return{from:l,to:r,type:s,animate:i}},this.addBar=function(t){e.bars.push(t),e.totalPercent+=t.to},this.clearBars=function(){e.bars=[],e.totalPercent=0},this.clearBars()}]).directive("progress",function(){return{restrict:"EA",replace:!0,controller:"ProgressBarController",scope:{value:"=percent",onFull:"&",onEmpty:"&"},templateUrl:"template/progressbar/progress.html",link:function(e,t,n,a){e.$watch("value",function(e,t){if(a.clearBars(),angular.isArray(e))for(var n=0,i=e.length;i>n;n++)a.addBar(a.makeBar(e[n],t[n],n));else a.addBar(a.makeBar(e,t))},!0),e.$watch("totalPercent",function(t){t>=100?e.onFull():0>=t&&e.onEmpty()},!0)}}}).directive("progressbar",["$transition",function(e){return{restrict:"EA",replace:!0,scope:{width:"=",old:"=",type:"=",animate:"="},templateUrl:"template/progressbar/bar.html",link:function(t,n){t.$watch("width",function(a){t.animate?(n.css("width",t.old+"%"),e(n,{width:a+"%"})):n.css("width",a+"%")})}}}]),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5}).directive("rating",["ratingConfig","$parse",function(e,t){return{restrict:"EA",scope:{value:"=",onHover:"&",onLeave:"&"},templateUrl:"template/rating/rating.html",replace:!0,link:function(n,a,i){var o=angular.isDefined(i.max)?n.$parent.$eval(i.max):e.max;n.range=[];for(var r=1;o>=r;r++)n.range.push(r);n.rate=function(e){n.readonly||(n.value=e)},n.enter=function(e){n.readonly||(n.val=e),n.onHover({value:e})},n.reset=function(){n.val=angular.copy(n.value),n.onLeave()},n.reset(),n.$watch("value",function(e){n.val=e}),n.readonly=!1,i.readonly&&n.$parent.$watch(t(i.readonly),function(e){n.readonly=!!e})}}}]),angular.module("ui.bootstrap.tabs",[]).directive("tabs",function(){return function(){throw Error("The `tabs` directive is deprecated, please migrate to `tabset`. Instructions can be found at http://github.com/angular-ui/bootstrap/tree/master/CHANGELOG.md")}}).controller("TabsetController",["$scope","$element",function(e){var t=this,n=t.tabs=e.tabs=[];t.select=function(e){angular.forEach(n,function(e){e.active=!1}),e.active=!0},t.addTab=function(e){n.push(e),(1===n.length||e.active)&&t.select(e)},t.removeTab=function(e){var a=n.indexOf(e);if(e.active&&n.length>1){var i=a==n.length-1?a-1:a+1;t.select(n[i])}n.splice(a,1)}}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,require:"^tabset",scope:{},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",compile:function(e,t,n){return function(e,t,a,i){e.vertical=angular.isDefined(a.vertical)?e.$eval(a.vertical):!1,e.type=angular.isDefined(a.type)?e.$parent.$eval(a.type):"tabs",e.direction=angular.isDefined(a.direction)?e.$parent.$eval(a.direction):"top",e.tabsAbove="below"!=e.direction,i.$scope=e,i.$transcludeFn=n}}}}).directive("tab",["$parse","$http","$templateCache","$compile",function(e){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(t,n,a){return function(t,n,i,o){var r,l;i.active?(r=e(i.active),l=r.assign,t.$parent.$watch(r,function(e){t.active=!!e}),t.active=r(t.$parent)):l=r=angular.noop,t.$watch("active",function(e){l(t.$parent,e),e?(o.select(t),t.onSelect()):t.onDeselect()}),t.disabled=!1,i.disabled&&t.$parent.$watch(e(i.disabled),function(e){t.disabled=!!e}),t.select=function(){t.disabled||(t.active=!0)},o.addTab(t),t.$on("$destroy",function(){o.removeTab(t)}),t.active&&l(t.$parent,!0),t.$transcludeFn=a}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(e,t){e.$watch("headingElement",function(e){e&&(t.html(""),t.append(e))})}}}]).directive("tabContentTransclude",["$compile","$parse",function(){function e(e){return e.tagName&&(e.hasAttribute("tab-heading")||e.hasAttribute("data-tab-heading")||"tab-heading"===e.tagName.toLowerCase()||"data-tab-heading"===e.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(t,n,a){var i=t.$eval(a.tabContentTransclude);i.$transcludeFn(i.$parent,function(t){angular.forEach(t,function(t){e(t)?i.headingElement=t:n.append(t) -})})}}}]).directive("tabsetTitles",function(){return{restrict:"A",require:"^tabset",templateUrl:"template/tabs/tabset-titles.html",replace:!0,link:function(e,t,n,a){e.$eval(n.tabsetTitles)?a.$transcludeFn(a.$scope.$parent,function(e){t.append(e)}):t.remove()}}}),angular.module("ui.bootstrap.timepicker",[]).filter("pad",function(){return function(e){return angular.isDefined(e)&&2>(""+e).length&&(e="0"+e),e}}).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:["AM","PM"],readonlyInput:!1,mousewheel:!0}).directive("timepicker",["padFilter","$parse","timepickerConfig",function(e,t,n){return{restrict:"EA",require:"ngModel",replace:!0,templateUrl:"template/timepicker/timepicker.html",scope:{model:"=ngModel"},link:function(a,i,o){function r(){var e=parseInt(a.hours,10),t=a.showMeridian?e>0&&13>e:e>=0&&24>e;return t?(a.showMeridian&&(12===e&&(e=0),a.meridian===u[1]&&(e+=12)),e):void 0}function l(){var t=c.getHours();a.showMeridian&&(t=0===t||12===t?12:t%12),a.hours="h"===b?t:e(t),a.validHours=!0;var n=c.getMinutes();a.minutes="m"===b?n:e(n),a.validMinutes=!0,a.meridian=a.showMeridian?12>c.getHours()?u[0]:u[1]:"",b=!1}function s(e){var t=new Date(c.getTime()+6e4*e);c.setHours(t.getHours()),c.setMinutes(t.getMinutes()),a.model=new Date(c)}var c=new Date,u=n.meridians,p=n.hourStep;o.hourStep&&a.$parent.$watch(t(o.hourStep),function(e){p=parseInt(e,10)});var d=n.minuteStep;o.minuteStep&&a.$parent.$watch(t(o.minuteStep),function(e){d=parseInt(e,10)}),a.showMeridian=n.showMeridian,o.showMeridian&&a.$parent.$watch(t(o.showMeridian),function(e){if(a.showMeridian=!!e,a.model)l();else{var t=new Date(c),n=r();angular.isDefined(n)&&t.setHours(n),a.model=new Date(t)}});var f=i.find("input"),m=f.eq(0),g=f.eq(1),h=angular.isDefined(o.mousewheel)?a.$eval(o.mousewheel):n.mousewheel;if(h){var v=function(e){e.originalEvent&&(e=e.originalEvent);var t=e.wheelDelta?e.wheelDelta:-e.deltaY;return e.detail||t>0};m.bind("mousewheel wheel",function(e){a.$apply(v(e)?a.incrementHours():a.decrementHours()),e.preventDefault()}),g.bind("mousewheel wheel",function(e){a.$apply(v(e)?a.incrementMinutes():a.decrementMinutes()),e.preventDefault()})}var b=!1;a.readonlyInput=angular.isDefined(o.readonlyInput)?a.$eval(o.readonlyInput):n.readonlyInput,a.readonlyInput?(a.updateHours=angular.noop,a.updateMinutes=angular.noop):(a.updateHours=function(){var e=r();angular.isDefined(e)?(b="h",null===a.model&&(a.model=new Date(c)),a.model.setHours(e)):(a.model=null,a.validHours=!1)},m.bind("blur",function(){a.validHours&&10>a.hours&&a.$apply(function(){a.hours=e(a.hours)})}),a.updateMinutes=function(){var e=parseInt(a.minutes,10);e>=0&&60>e?(b="m",null===a.model&&(a.model=new Date(c)),a.model.setMinutes(e)):(a.model=null,a.validMinutes=!1)},g.bind("blur",function(){a.validMinutes&&10>a.minutes&&a.$apply(function(){a.minutes=e(a.minutes)})})),a.$watch(function(){return+a.model},function(e){!isNaN(e)&&e>0&&(c=new Date(e),l())}),a.incrementHours=function(){s(60*p)},a.decrementHours=function(){s(60*-p)},a.incrementMinutes=function(){s(d)},a.decrementMinutes=function(){s(-d)},a.toggleMeridian=function(){s(720*(12>c.getHours()?1:-1))}}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position"]).factory("typeaheadParser",["$parse",function(e){var t=/^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;return{parse:function(n){var a=n.match(t);if(!a)throw Error("Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_' but got '"+n+"'.");return{itemName:a[3],source:e(a[4]),viewMapper:e(a[2]||a[1]),modelMapper:e(a[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(e,t,n,a,i,o,r){var l=[9,13,27,38,40];return{require:"ngModel",link:function(s,c,u,p){var d=s.$eval(u.typeaheadMinLength)||1,f=s.$eval(u.typeaheadWaitMs)||0,m=s.$eval(u.typeaheadEditable)!==!1,g=t(u.typeaheadLoading).assign||angular.noop,h=t(u.typeaheadOnSelect),v=u.typeaheadInputFormatter?t(u.typeaheadInputFormatter):void 0,b=t(u.ngModel).assign,$=r.parse(u.typeahead),y=angular.element("");y.attr({matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(u.typeaheadTemplateUrl)&&y.attr("template-url",u.typeaheadTemplateUrl);var w=s.$new();s.$on("$destroy",function(){w.$destroy()});var k=function(){w.matches=[],w.activeIdx=-1},D=function(e){var t={$viewValue:e};g(s,!0),n.when($.source(w,t)).then(function(n){if(e===p.$viewValue){if(n.length>0){w.activeIdx=0,w.matches.length=0;for(var a=0;n.length>a;a++)t[$.itemName]=n[a],w.matches.push({label:$.viewMapper(w,t),model:n[a]});w.query=e,w.position=o.position(c),w.position.top=w.position.top+c.prop("offsetHeight")}else k();g(s,!1)}},function(){k(),g(s,!1)})};k(),w.query=void 0;var x;p.$parsers.push(function(e){return k(),e&&e.length>=d&&(f>0?(x&&a.cancel(x),x=a(function(){D(e)},f)):D(e)),m?e:void 0}),p.$formatters.push(function(e){var t,n,a={};return v?(a.$model=e,v(s,a)):(a[$.itemName]=e,t=$.viewMapper(s,a),n=$.viewMapper(s,{}),t!==n?t:e)}),w.select=function(e){var t,n,a={};a[$.itemName]=n=w.matches[e].model,t=$.modelMapper(s,a),b(s,t),h(s,{$item:n,$model:t,$label:$.viewMapper(s,a)}),k(),c[0].focus()},c.bind("keydown",function(e){0!==w.matches.length&&-1!==l.indexOf(e.which)&&(e.preventDefault(),40===e.which?(w.activeIdx=(w.activeIdx+1)%w.matches.length,w.$digest()):38===e.which?(w.activeIdx=(w.activeIdx?w.activeIdx:w.matches.length)-1,w.$digest()):13===e.which||9===e.which?w.$apply(function(){w.select(w.activeIdx)}):27===e.which&&(e.stopPropagation(),k(),w.$digest()))}),i.bind("click",function(){k(),w.$digest()}),c.after(e(y)(w))}}}]).directive("typeaheadPopup",function(){return{restrict:"E",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(e,t,n){e.templateUrl=n.templateUrl,e.isOpen=function(){return e.matches.length>0},e.isActive=function(t){return e.active==t},e.selectActive=function(t){e.active=t},e.selectMatch=function(t){e.select({activeIdx:t})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(e,t,n,a){return{restrict:"E",scope:{index:"=",match:"=",query:"="},link:function(i,o,r){var l=a(r.templateUrl)(i.$parent)||"template/typeahead/typeahead-match.html";e.get(l,{cache:t}).success(function(e){o.replaceWith(n(e.trim())(i))})}}}]).filter("typeaheadHighlight",function(){function e(e){return e.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(t,n){return n?t.replace(RegExp(e(n),"gi"),"$&"):n}}); \ No newline at end of file +angular.module("ui.bootstrap",["ui.bootstrap.transition","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.bindHtml","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdownToggle","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"]),angular.module("ui.bootstrap.transition",[]).factory("$transition",["$q","$timeout","$rootScope",function(e,t,n){function a(e){for(var t in e)if(void 0!==r.style[t])return e[t]}var i=function(a,r,o){o=o||{};var l=e.defer(),c=i[o.animation?"animationEndEventName":"transitionEndEventName"],s=function(){n.$apply(function(){a.unbind(c,s),l.resolve(a)})};return c&&a.bind(c,s),t(function(){angular.isString(r)?a.addClass(r):angular.isFunction(r)?r(a):angular.isObject(r)&&a.css(r),c||l.resolve(a)}),l.promise.cancel=function(){c&&a.unbind(c,s),l.reject("Transition cancelled")},l.promise},r=document.createElement("trans"),o={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",transition:"transitionend"},l={WebkitTransition:"webkitAnimationEnd",MozTransition:"animationend",OTransition:"oAnimationEnd",transition:"animationend"};return i.transitionEndEventName=a(o),i.animationEndEventName=a(l),i}]),angular.module("ui.bootstrap.collapse",["ui.bootstrap.transition"]).directive("collapse",["$transition",function(e){var t=function(e,t,n){t.removeClass("collapse"),t.css({height:n}),t[0].offsetWidth,t.addClass("collapse")};return{link:function(n,a,i){var r,o=!0;n.$watch(function(){return a[0].scrollHeight},function(){0!==a[0].scrollHeight&&(r||(o?t(n,a,a[0].scrollHeight+"px"):t(n,a,"auto")))}),n.$watch(i.collapse,function(e){e?u():s()});var l,c=function(t){return l&&l.cancel(),l=e(a,t),l.then(function(){l=void 0},function(){l=void 0}),l},s=function(){o?(o=!1,r||t(n,a,"auto")):c({height:a[0].scrollHeight+"px"}).then(function(){r||t(n,a,"auto")}),r=!1},u=function(){r=!0,o?(o=!1,t(n,a,0)):(t(n,a,a[0].scrollHeight+"px"),c({height:"0"}))}}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("accordionConfig",{closeOthers:!0}).controller("AccordionController",["$scope","$attrs","accordionConfig",function(e,t,n){this.groups=[],this.closeOthers=function(a){var i=angular.isDefined(t.closeOthers)?e.$eval(t.closeOthers):n.closeOthers;i&&angular.forEach(this.groups,function(e){e!==a&&(e.isOpen=!1)})},this.addGroup=function(e){var t=this;this.groups.push(e),e.$on("$destroy",function(){t.removeGroup(e)})},this.removeGroup=function(e){var t=this.groups.indexOf(e);-1!==t&&this.groups.splice(this.groups.indexOf(e),1)}}]).directive("accordion",function(){return{restrict:"EA",controller:"AccordionController",transclude:!0,replace:!1,templateUrl:"template/accordion/accordion.html"}}).directive("accordionGroup",["$parse","$transition","$timeout",function(e){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/accordion/accordion-group.html",scope:{heading:"@"},controller:["$scope",function(){this.setHeading=function(e){this.heading=e}}],link:function(t,n,a,i){var r,o;i.addGroup(t),t.isOpen=!1,a.isOpen&&(r=e(a.isOpen),o=r.assign,t.$watch(function(){return r(t.$parent)},function(e){t.isOpen=e}),t.isOpen=r?r(t.$parent):!1),t.$watch("isOpen",function(e){e&&i.closeOthers(t),o&&o(t.$parent,e)})}}}]).directive("accordionHeading",function(){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",compile:function(e,t,n){return function(e,t,a,i){i.setHeading(n(e,function(){}))}}}}).directive("accordionTransclude",function(){return{require:"^accordionGroup",link:function(e,t,n,a){e.$watch(function(){return a[n.accordionTransclude]},function(e){e&&(t.html(""),t.append(e))})}}}),angular.module("ui.bootstrap.alert",[]).directive("alert",function(){return{restrict:"EA",templateUrl:"template/alert/alert.html",transclude:!0,replace:!0,scope:{type:"=",close:"&"},link:function(e,t,n){e.closeable="close"in n}}}),angular.module("ui.bootstrap.bindHtml",[]).directive("bindHtmlUnsafe",function(){return function(e,t,n){t.addClass("ng-binding").data("$binding",n.bindHtmlUnsafe),e.$watch(n.bindHtmlUnsafe,function(e){t.html(e||"")})}}),angular.module("ui.bootstrap.buttons",[]).constant("buttonConfig",{activeClass:"active",toggleEvent:"click"}).directive("btnRadio",["buttonConfig",function(e){var t=e.activeClass||"active",n=e.toggleEvent||"click";return{require:"ngModel",link:function(e,a,i,r){r.$render=function(){a.toggleClass(t,angular.equals(r.$modelValue,e.$eval(i.btnRadio)))},a.bind(n,function(){a.hasClass(t)||e.$apply(function(){r.$setViewValue(e.$eval(i.btnRadio)),r.$render()})})}}}]).directive("btnCheckbox",["buttonConfig",function(e){var t=e.activeClass||"active",n=e.toggleEvent||"click";return{require:"ngModel",link:function(e,a,i,r){function o(){var t=e.$eval(i.btnCheckboxTrue);return angular.isDefined(t)?t:!0}function l(){var t=e.$eval(i.btnCheckboxFalse);return angular.isDefined(t)?t:!1}r.$render=function(){a.toggleClass(t,angular.equals(r.$modelValue,o()))},a.bind(n,function(){e.$apply(function(){r.$setViewValue(a.hasClass(t)?l():o()),r.$render()})})}}}]),angular.module("ui.bootstrap.carousel",["ui.bootstrap.transition"]).controller("CarouselController",["$scope","$timeout","$transition","$q",function(e,t,n){function a(){function n(){r?(e.next(),a()):e.pause()}i&&t.cancel(i);var o=+e.interval;!isNaN(o)&&o>=0&&(i=t(n,o))}var i,r,o=this,l=o.slides=[],c=-1;o.currentSlide=null,o.select=function(i,r){function s(){o.currentSlide&&angular.isString(r)&&!e.noTransition&&i.$element?(i.$element.addClass(r),i.$element[0].offsetWidth,angular.forEach(l,function(e){angular.extend(e,{direction:"",entering:!1,leaving:!1,active:!1})}),angular.extend(i,{direction:r,active:!0,entering:!0}),angular.extend(o.currentSlide||{},{direction:r,leaving:!0}),e.$currentTransition=n(i.$element,{}),function(t,n){e.$currentTransition.then(function(){u(t,n)},function(){u(t,n)})}(i,o.currentSlide)):u(i,o.currentSlide),o.currentSlide=i,c=p,a()}function u(t,n){angular.extend(t,{direction:"",active:!0,leaving:!1,entering:!1}),angular.extend(n||{},{direction:"",active:!1,leaving:!1,entering:!1}),e.$currentTransition=null}var p=l.indexOf(i);void 0===r&&(r=p>c?"next":"prev"),i&&i!==o.currentSlide&&(e.$currentTransition?(e.$currentTransition.cancel(),t(s)):s())},o.indexOfSlide=function(e){return l.indexOf(e)},e.next=function(){var t=(c+1)%l.length;return e.$currentTransition?void 0:o.select(l[t],"next")},e.prev=function(){var t=0>c-1?l.length-1:c-1;return e.$currentTransition?void 0:o.select(l[t],"prev")},e.select=function(e){o.select(e)},e.isActive=function(e){return o.currentSlide===e},e.slides=function(){return l},e.$watch("interval",a),e.play=function(){r||(r=!0,a())},e.pause=function(){e.noPause||(r=!1,i&&t.cancel(i))},o.addSlide=function(t,n){t.$element=n,l.push(t),1===l.length||t.active?(o.select(l[l.length-1]),1==l.length&&e.play()):t.active=!1},o.removeSlide=function(e){var t=l.indexOf(e);l.splice(t,1),l.length>0&&e.active?t>=l.length?o.select(l[t-1]):o.select(l[t]):c>t&&c--}}]).directive("carousel",[function(){return{restrict:"EA",transclude:!0,replace:!0,controller:"CarouselController",require:"carousel",templateUrl:"template/carousel/carousel.html",scope:{interval:"=",noTransition:"=",noPause:"="}}}]).directive("slide",["$parse",function(e){return{require:"^carousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:"template/carousel/slide.html",scope:{},link:function(t,n,a,i){if(a.active){var r=e(a.active),o=r.assign,l=t.active=r(t.$parent);t.$watch(function(){var e=r(t.$parent);return e!==t.active&&(e!==l?l=t.active=e:o(t.$parent,e=l=t.active)),e})}i.addSlide(t,n),t.$on("$destroy",function(){i.removeSlide(t)}),t.$watch("active",function(e){e&&i.select(t)})}}}]),angular.module("ui.bootstrap.position",[]).factory("$position",["$document","$window",function(e,t){function n(e,n){return e.currentStyle?e.currentStyle[n]:t.getComputedStyle?t.getComputedStyle(e)[n]:e.style[n]}function a(e){return"static"===(n(e,"position")||"static")}var i=function(t){for(var n=e[0],i=t.offsetParent||n;i&&i!==n&&a(i);)i=i.offsetParent;return i||n};return{position:function(t){var n=this.offset(t),a={top:0,left:0},r=i(t[0]);return r!=e[0]&&(a=this.offset(angular.element(r)),a.top+=r.clientTop-r.scrollTop,a.left+=r.clientLeft-r.scrollLeft),{width:t.prop("offsetWidth"),height:t.prop("offsetHeight"),top:n.top-a.top,left:n.left-a.left}},offset:function(n){var a=n[0].getBoundingClientRect();return{width:n.prop("offsetWidth"),height:n.prop("offsetHeight"),top:a.top+(t.pageYOffset||e[0].body.scrollTop||e[0].documentElement.scrollTop),left:a.left+(t.pageXOffset||e[0].body.scrollLeft||e[0].documentElement.scrollLeft)}}}}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.position"]).constant("datepickerConfig",{dayFormat:"dd",monthFormat:"MMMM",yearFormat:"yyyy",dayHeaderFormat:"EEE",dayTitleFormat:"MMMM yyyy",monthTitleFormat:"yyyy",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null}).controller("DatepickerController",["$scope","$attrs","dateFilter","datepickerConfig",function(e,t,n,a){function i(t,n){return angular.isDefined(t)?e.$parent.$eval(t):n}function r(e,t){return new Date(e,t,0).getDate()}function o(e,t){for(var n=Array(t),a=e,i=0;t>i;)n[i++]=new Date(a),a.setDate(a.getDate()+1);return n}function l(e,t,a,i){return{date:e,label:n(e,t),selected:!!a,secondary:!!i}}var c={day:i(t.dayFormat,a.dayFormat),month:i(t.monthFormat,a.monthFormat),year:i(t.yearFormat,a.yearFormat),dayHeader:i(t.dayHeaderFormat,a.dayHeaderFormat),dayTitle:i(t.dayTitleFormat,a.dayTitleFormat),monthTitle:i(t.monthTitleFormat,a.monthTitleFormat)},s=i(t.startingDay,a.startingDay),u=i(t.yearRange,a.yearRange);this.minDate=a.minDate?new Date(a.minDate):null,this.maxDate=a.maxDate?new Date(a.maxDate):null,this.modes=[{name:"day",getVisibleDates:function(e,t){var a=e.getFullYear(),i=e.getMonth(),u=new Date(a,i,1),p=s-u.getDay(),d=p>0?7-p:-p,f=new Date(u),m=0;d>0&&(f.setDate(-d+1),m+=d),m+=r(a,i+1),m+=(7-m%7)%7;for(var g=o(f,m),h=Array(7),v=0;m>v;v++){var $=new Date(g[v]);g[v]=l($,c.day,t&&t.getDate()===$.getDate()&&t.getMonth()===$.getMonth()&&t.getFullYear()===$.getFullYear(),$.getMonth()!==i)}for(var b=0;7>b;b++)h[b]=n(g[b].date,c.dayHeader);return{objects:g,title:n(e,c.dayTitle),labels:h}},compare:function(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate())-new Date(t.getFullYear(),t.getMonth(),t.getDate())},split:7,step:{months:1}},{name:"month",getVisibleDates:function(e,t){for(var a=Array(12),i=e.getFullYear(),r=0;12>r;r++){var o=new Date(i,r,1);a[r]=l(o,c.month,t&&t.getMonth()===r&&t.getFullYear()===i)}return{objects:a,title:n(e,c.monthTitle)}},compare:function(e,t){return new Date(e.getFullYear(),e.getMonth())-new Date(t.getFullYear(),t.getMonth())},split:3,step:{years:1}},{name:"year",getVisibleDates:function(e,t){for(var n=Array(u),a=e.getFullYear(),i=parseInt((a-1)/u,10)*u+1,r=0;u>r;r++){var o=new Date(i+r,0,1);n[r]=l(o,c.year,t&&t.getFullYear()===o.getFullYear())}return{objects:n,title:[n[0].label,n[u-1].label].join(" - ")}},compare:function(e,t){return e.getFullYear()-t.getFullYear()},split:5,step:{years:u}}],this.isDisabled=function(t,n){var a=this.modes[n||0];return this.minDate&&0>a.compare(t,this.minDate)||this.maxDate&&a.compare(t,this.maxDate)>0||e.dateDisabled&&e.dateDisabled({date:t,mode:a.name})}}]).directive("datepicker",["dateFilter","$parse","datepickerConfig","$log",function(e,t,n,a){return{restrict:"EA",replace:!0,templateUrl:"template/datepicker/datepicker.html",scope:{dateDisabled:"&"},require:["datepicker","?^ngModel"],controller:"DatepickerController",link:function(e,i,r,o){function l(){e.showWeekNumbers=0===m&&h}function c(e,t){for(var n=[];e.length>0;)n.push(e.splice(0,t));return n}function s(t){var n=null,i=!0;f.$modelValue&&(n=new Date(f.$modelValue),isNaN(n)?(i=!1,a.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.')):t&&(g=n)),f.$setValidity("date",i);var r=d.modes[m],o=r.getVisibleDates(g,n);angular.forEach(o.objects,function(e){e.disabled=d.isDisabled(e.date,m)}),f.$setValidity("date-disabled",!n||!d.isDisabled(n)),e.rows=c(o.objects,r.split),e.labels=o.labels||[],e.title=o.title}function u(e){m=e,l(),s()}function p(e){var t=new Date(e);t.setDate(t.getDate()+4-(t.getDay()||7));var n=t.getTime();return t.setMonth(0),t.setDate(1),Math.floor(Math.round((n-t)/864e5)/7)+1}var d=o[0],f=o[1];if(f){var m=0,g=new Date,h=n.showWeeks;r.showWeeks?e.$parent.$watch(t(r.showWeeks),function(e){h=!!e,l()}):l(),r.min&&e.$parent.$watch(t(r.min),function(e){d.minDate=e?new Date(e):null,s()}),r.max&&e.$parent.$watch(t(r.max),function(e){d.maxDate=e?new Date(e):null,s()}),f.$render=function(){s(!0)},e.select=function(e){if(0===m){var t=new Date(f.$modelValue);t.setFullYear(e.getFullYear(),e.getMonth(),e.getDate()),f.$setViewValue(t),s(!0)}else g=e,u(m-1)},e.move=function(e){var t=d.modes[m].step;g.setMonth(g.getMonth()+e*(t.months||0)),g.setFullYear(g.getFullYear()+e*(t.years||0)),s()},e.toggleMode=function(){u((m+1)%d.modes.length)},e.getWeekNumber=function(t){return 0===m&&e.showWeekNumbers&&7===t.length?p(t[0].date):null}}}}}]).constant("datepickerPopupConfig",{dateFormat:"yyyy-MM-dd",closeOnDateSelection:!0}).directive("datepickerPopup",["$compile","$parse","$document","$position","dateFilter","datepickerPopupConfig",function(e,t,n,a,i,r){return{restrict:"EA",require:"ngModel",link:function(o,l,c,s){function u(e){b?b(o,!!e):v.isOpen=!!e}function p(e){if(e){if(angular.isDate(e))return s.$setValidity("date",!0),e;if(angular.isString(e)){var t=new Date(e);return isNaN(t)?(s.$setValidity("date",!1),void 0):(s.$setValidity("date",!0),t)}return s.$setValidity("date",!1),void 0}return s.$setValidity("date",!0),null}function d(){v.date=s.$modelValue,m()}function f(e,n,a){e&&(o.$watch(t(e),function(e){v[n]=e}),D.attr(a||n,n))}function m(){v.position=a.position(l),v.position.top=v.position.top+l.prop("offsetHeight")}var g=angular.isDefined(c.closeOnDateSelection)?v.$eval(c.closeOnDateSelection):r.closeOnDateSelection,h=c.datepickerPopup||r.dateFormat,v=o.$new();o.$on("$destroy",function(){v.$destroy()});var $,b;c.isOpen&&($=t(c.isOpen),b=$.assign,o.$watch($,function(e){v.isOpen=!!e})),v.isOpen=$?$(o):!1;var y=function(e){v.isOpen&&e.target!==l[0]&&v.$apply(function(){u(!1)})},w=function(){v.$apply(function(){u(!0)})},k=angular.element("");k.attr({"ng-model":"date","ng-change":"dateSelection()"});var D=k.find("datepicker");c.datepickerOptions&&D.attr(angular.extend({},o.$eval(c.datepickerOptions))),s.$parsers.unshift(p),v.dateSelection=function(){s.$setViewValue(v.date),s.$render(),g&&u(!1)},l.bind("input change keyup",function(){v.$apply(function(){d()})}),s.$render=function(){var e=s.$viewValue?i(s.$viewValue,h):"";l.val(e),d()},f(c.min,"min"),f(c.max,"max"),c.showWeeks?f(c.showWeeks,"showWeeks","show-weeks"):(v.showWeeks=!0,D.attr("show-weeks","showWeeks")),c.dateDisabled&&D.attr("date-disabled",c.dateDisabled);var x=!1,T=!1;v.$watch("isOpen",function(e){e?(m(),n.bind("click",y),T&&l.unbind("focus",w),l[0].focus(),x=!0):(x&&n.unbind("click",y),l.bind("focus",w),T=!0),b&&b(o,e)});var M=t(c.ngModel).assign;v.today=function(){M(o,new Date)},v.clear=function(){M(o,null)},l.after(e(k)(v))}}}]).directive("datepickerPopupWrap",[function(){return{restrict:"E",replace:!0,transclude:!0,templateUrl:"template/datepicker/popup.html",link:function(e,t){t.bind("click",function(e){e.preventDefault(),e.stopPropagation()})}}}]),angular.module("ui.bootstrap.dropdownToggle",[]).directive("dropdownToggle",["$document","$location",function(e){var t=null,n=angular.noop;return{restrict:"CA",link:function(a,i){a.$watch("$location.path",function(){n()}),i.parent().bind("click",function(){n()}),i.bind("click",function(a){var r=i===t;a.preventDefault(),a.stopPropagation(),t&&n(),r||(i.parent().addClass("open"),t=i,n=function(a){a&&(a.preventDefault(),a.stopPropagation()),e.unbind("click",n),i.parent().removeClass("open"),n=angular.noop,t=null},e.bind("click",n))})}}}]),angular.module("ui.bootstrap.modal",[]).factory("$$stackedMap",function(){return{createNew:function(){var e=[];return{add:function(t,n){e.push({key:t,value:n})},get:function(t){for(var n=0;e.length>n;n++)if(t==e[n].key)return e[n]},keys:function(){for(var t=[],n=0;e.length>n;n++)t.push(e[n].key);return t},top:function(){return e[e.length-1]},remove:function(t){for(var n=-1,a=0;e.length>a;a++)if(t==e[a].key){n=a;break}return e.splice(n,1)[0]},removeTop:function(){return e.splice(e.length-1,1)[0]},length:function(){return e.length}}}}}).directive("modalBackdrop",["$modalStack","$timeout",function(e,t){return{restrict:"EA",replace:!0,templateUrl:"template/modal/backdrop.html",link:function(n){t(function(){n.animate=!0}),n.close=function(t){var n=e.getTop();n&&n.value.backdrop&&"static"!=n.value.backdrop&&(t.preventDefault(),t.stopPropagation(),e.dismiss(n.key,"backdrop click"))}}}}]).directive("modalWindow",["$timeout",function(e){return{restrict:"EA",scope:{index:"@"},replace:!0,transclude:!0,templateUrl:"template/modal/window.html",link:function(t,n,a){t.windowClass=a.windowClass||"",e(function(){t.animate=!0})}}}]).factory("$modalStack",["$document","$compile","$rootScope","$$stackedMap",function(e,t,n,a){function i(){for(var e=-1,t=u.keys(),n=0;t.length>n;n++)u.get(t[n]).value.backdrop&&(e=n);return e}function r(e){var t=u.get(e).value;u.remove(e),t.modalDomEl.remove(),-1==i()&&(l.remove(),l=void 0),t.modalScope.$destroy()}var o,l,c=n.$new(!0),s=e.find("body").eq(0),u=a.createNew(),p={};return n.$watch(i,function(e){c.index=e}),e.bind("keydown",function(e){var t;27===e.which&&(t=u.top(),t&&t.value.keyboard&&n.$apply(function(){p.dismiss(t.key)}))}),p.open=function(e,n){u.add(e,{deferred:n.deferred,modalScope:n.scope,backdrop:n.backdrop,keyboard:n.keyboard});var a=angular.element("
    ");a.attr("window-class",n.windowClass),a.attr("index",u.length()-1),a.html(n.content);var r=t(a)(n.scope);u.top().value.modalDomEl=r,s.append(r),i()>=0&&!l&&(o=angular.element("
    "),l=t(o)(c),s.append(l))},p.close=function(e,t){var n=u.get(e);n&&(n.value.deferred.resolve(t),r(e))},p.dismiss=function(e,t){var n=u.get(e).value;n&&(n.deferred.reject(t),r(e))},p.getTop=function(){return u.top()},p}]).provider("$modal",function(){var e={options:{backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$http","$templateCache","$controller","$modalStack",function(t,n,a,i,r,o,l){function c(e){return e.template?a.when(e.template):i.get(e.templateUrl,{cache:r}).then(function(e){return e.data})}function s(e){var n=[];return angular.forEach(e,function(e){(angular.isFunction(e)||angular.isArray(e))&&n.push(a.when(t.invoke(e)))}),n}var u={};return u.open=function(t){var i=a.defer(),r=a.defer(),u={result:i.promise,opened:r.promise,close:function(e){l.close(u,e)},dismiss:function(e){l.dismiss(u,e)}};if(t=angular.extend({},e.options,t),t.resolve=t.resolve||{},!t.template&&!t.templateUrl)throw Error("One of template or templateUrl options is required.");var p=a.all([c(t)].concat(s(t.resolve)));return p.then(function(e){var a=(t.scope||n).$new();a.$close=u.close,a.$dismiss=u.dismiss;var r,c={},s=1;t.controller&&(c.$scope=a,c.$modalInstance=u,angular.forEach(t.resolve,function(t,n){c[n]=e[s++]}),r=o(t.controller,c)),l.open(u,{scope:a,deferred:i,content:e[0],backdrop:t.backdrop,keyboard:t.keyboard,windowClass:t.windowClass})},function(e){i.reject(e)}),p.then(function(){r.resolve(!0)},function(){r.reject(!1)}),u},u}]};return e}),angular.module("ui.bootstrap.pagination",[]).controller("PaginationController",["$scope","$attrs","$parse","$interpolate",function(e,t,n,a){var i=this;this.init=function(a){t.itemsPerPage?e.$parent.$watch(n(t.itemsPerPage),function(t){i.itemsPerPage=parseInt(t,10),e.totalPages=i.calculateTotalPages()}):this.itemsPerPage=a},this.noPrevious=function(){return 1===this.page},this.noNext=function(){return this.page===e.totalPages},this.isActive=function(e){return this.page===e},this.calculateTotalPages=function(){return 1>this.itemsPerPage?1:Math.ceil(e.totalItems/this.itemsPerPage)},this.getAttributeValue=function(t,n,i){return angular.isDefined(t)?i?a(t)(e.$parent):e.$parent.$eval(t):n},this.render=function(){this.page=parseInt(e.page,10)||1,e.pages=this.getPages(this.page,e.totalPages)},e.selectPage=function(t){!i.isActive(t)&&t>0&&e.totalPages>=t&&(e.page=t,e.onSelectPage({page:t}))},e.$watch("totalItems",function(){e.totalPages=i.calculateTotalPages()}),e.$watch("totalPages",function(n){t.numPages&&(e.numPages=n),i.page>n?e.selectPage(n):i.render()}),e.$watch("page",function(){i.render()})}]).constant("paginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("pagination",["$parse","paginationConfig",function(e,t){return{restrict:"EA",scope:{page:"=",totalItems:"=",onSelectPage:" &",numPages:"="},controller:"PaginationController",templateUrl:"template/pagination/pagination.html",replace:!0,link:function(n,a,i,r){function o(e,t,n,a){return{number:e,text:t,active:n,disabled:a}}var l,c=r.getAttributeValue(i.boundaryLinks,t.boundaryLinks),s=r.getAttributeValue(i.directionLinks,t.directionLinks),u=r.getAttributeValue(i.firstText,t.firstText,!0),p=r.getAttributeValue(i.previousText,t.previousText,!0),d=r.getAttributeValue(i.nextText,t.nextText,!0),f=r.getAttributeValue(i.lastText,t.lastText,!0),m=r.getAttributeValue(i.rotate,t.rotate);r.init(t.itemsPerPage),i.maxSize&&n.$parent.$watch(e(i.maxSize),function(e){l=parseInt(e,10),r.render()}),r.getPages=function(e,t){var n=[],a=1,i=t,g=angular.isDefined(l)&&t>l;g&&(m?(a=Math.max(e-Math.floor(l/2),1),i=a+l-1,i>t&&(i=t,a=i-l+1)):(a=(Math.ceil(e/l)-1)*l+1,i=Math.min(a+l-1,t)));for(var h=a;i>=h;h++){var v=o(h,h,r.isActive(h),!1);n.push(v)}if(g&&!m){if(a>1){var $=o(a-1,"...",!1,!1);n.unshift($)}if(t>i){var b=o(i+1,"...",!1,!1);n.push(b)}}if(s){var y=o(e-1,p,!1,r.noPrevious());n.unshift(y);var w=o(e+1,d,!1,r.noNext());n.push(w)}if(c){var k=o(1,u,!1,r.noPrevious());n.unshift(k);var D=o(t,f,!1,r.noNext());n.push(D)}return n}}}}]).constant("pagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("pager",["pagerConfig",function(e){return{restrict:"EA",scope:{page:"=",totalItems:"=",onSelectPage:" &",numPages:"="},controller:"PaginationController",templateUrl:"template/pagination/pager.html",replace:!0,link:function(t,n,a,i){function r(e,t,n,a,i){return{number:e,text:t,disabled:n,previous:c&&a,next:c&&i}}var o=i.getAttributeValue(a.previousText,e.previousText,!0),l=i.getAttributeValue(a.nextText,e.nextText,!0),c=i.getAttributeValue(a.align,e.align);i.init(e.itemsPerPage),i.getPages=function(e){return[r(e-1,o,i.noPrevious(),!0,!1),r(e+1,l,i.noNext(),!1,!0)]}}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).provider("$tooltip",function(){function e(e){var t=/[A-Z]/g,n="-";return e.replace(t,function(e,t){return(t?n:"")+e.toLowerCase()})}var t={placement:"top",animation:!0,popupDelay:0},n={mouseenter:"mouseleave",click:"click",focus:"blur"},a={};this.options=function(e){angular.extend(a,e)},this.setTriggers=function(e){angular.extend(n,e)},this.$get=["$window","$compile","$timeout","$parse","$document","$position","$interpolate",function(i,r,o,l,c,s,u){return function(i,p,d){function f(e){var t=e||m.trigger||d,a=n[t]||t;return{show:t,hide:a}}var m=angular.extend({},t,a),g=e(i),h=u.startSymbol(),v=u.endSymbol(),$="<"+g+"-popup "+'title="'+h+"tt_title"+v+'" '+'content="'+h+"tt_content"+v+'" '+'placement="'+h+"tt_placement"+v+'" '+'animation="tt_animation()" '+'is-open="tt_isOpen"'+">"+"";return{restrict:"EA",scope:!0,link:function(e,t,n){function a(){e.tt_isOpen?d():u()}function u(){e.tt_popupDelay?b=o(g,e.tt_popupDelay):e.$apply(g)}function d(){e.$apply(function(){h()})}function g(){var n,a,i,r;if(e.tt_content){switch(v&&o.cancel(v),w.css({top:0,left:0,display:"block"}),k?(y=y||c.find("body"),y.append(w)):t.after(w),n=k?s.offset(t):s.position(t),a=w.prop("offsetWidth"),i=w.prop("offsetHeight"),e.tt_placement){case"right":r={top:n.top+n.height/2-i/2,left:n.left+n.width};break;case"bottom":r={top:n.top+n.height,left:n.left+n.width/2-a/2};break;case"left":r={top:n.top+n.height/2-i/2,left:n.left-a};break;default:r={top:n.top-i,left:n.left+n.width/2-a/2}}r.top+="px",r.left+="px",w.css(r),e.tt_isOpen=!0}}function h(){e.tt_isOpen=!1,o.cancel(b),angular.isDefined(e.tt_animation)&&e.tt_animation()?v=o(function(){w.remove()},500):w.remove()}var v,b,y,w=r($)(e),k=angular.isDefined(m.appendToBody)?m.appendToBody:!1,D=f(void 0),x=!1;e.tt_isOpen=!1,n.$observe(i,function(t){e.tt_content=t}),n.$observe(p+"Title",function(t){e.tt_title=t}),n.$observe(p+"Placement",function(t){e.tt_placement=angular.isDefined(t)?t:m.placement}),n.$observe(p+"Animation",function(t){e.tt_animation=angular.isDefined(t)?l(t):function(){return m.animation}}),n.$observe(p+"PopupDelay",function(t){var n=parseInt(t,10);e.tt_popupDelay=isNaN(n)?m.popupDelay:n}),n.$observe(p+"Trigger",function(e){x&&(t.unbind(D.show,u),t.unbind(D.hide,d)),D=f(e),D.show===D.hide?t.bind(D.show,a):(t.bind(D.show,u),t.bind(D.hide,d)),x=!0}),n.$observe(p+"AppendToBody",function(t){k=angular.isDefined(t)?l(t)(e):k}),k&&e.$on("$locationChangeSuccess",function(){e.tt_isOpen&&h()}),e.$on("$destroy",function(){e.tt_isOpen?h():w.remove()})}}}}]}).directive("tooltipPopup",function(){return{restrict:"E",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html"}}).directive("tooltip",["$tooltip",function(e){return e("tooltip","tooltip","mouseenter")}]).directive("tooltipHtmlUnsafePopup",function(){return{restrict:"E",replace:!0,scope:{content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-unsafe-popup.html"}}).directive("tooltipHtmlUnsafe",["$tooltip",function(e){return e("tooltipHtmlUnsafe","tooltip","mouseenter")}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("popoverPopup",function(){return{restrict:"EA",replace:!0,scope:{title:"@",content:"@",placement:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html"}}).directive("popover",["$compile","$timeout","$parse","$window","$tooltip",function(e,t,n,a,i){return i("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",["ui.bootstrap.transition"]).constant("progressConfig",{animate:!0,autoType:!1,stackedTypes:["success","info","warning","danger"]}).controller("ProgressBarController",["$scope","$attrs","progressConfig",function(e,t,n){function a(e){return o[e]}var i=angular.isDefined(t.animate)?e.$eval(t.animate):n.animate,r=angular.isDefined(t.autoType)?e.$eval(t.autoType):n.autoType,o=angular.isDefined(t.stackedTypes)?e.$eval("["+t.stackedTypes+"]"):n.stackedTypes;this.makeBar=function(e,t,n){var o=angular.isObject(e)?e.value:e||0,l=angular.isObject(t)?t.value:t||0,c=angular.isObject(e)&&angular.isDefined(e.type)?e.type:r?a(n||0):null;return{from:l,to:o,type:c,animate:i}},this.addBar=function(t){e.bars.push(t),e.totalPercent+=t.to},this.clearBars=function(){e.bars=[],e.totalPercent=0},this.clearBars()}]).directive("progress",function(){return{restrict:"EA",replace:!0,controller:"ProgressBarController",scope:{value:"=percent",onFull:"&",onEmpty:"&"},templateUrl:"template/progressbar/progress.html",link:function(e,t,n,a){e.$watch("value",function(e,t){if(a.clearBars(),angular.isArray(e))for(var n=0,i=e.length;i>n;n++)a.addBar(a.makeBar(e[n],t[n],n));else a.addBar(a.makeBar(e,t))},!0),e.$watch("totalPercent",function(t){t>=100?e.onFull():0>=t&&e.onEmpty()},!0)}}}).directive("progressbar",["$transition",function(e){return{restrict:"EA",replace:!0,scope:{width:"=",old:"=",type:"=",animate:"="},templateUrl:"template/progressbar/bar.html",link:function(t,n){t.$watch("width",function(a){t.animate?(n.css("width",t.old+"%"),e(n,{width:a+"%"})):n.css("width",a+"%")})}}}]),angular.module("ui.bootstrap.rating",[]).constant("ratingConfig",{max:5,stateOn:null,stateOff:null}).controller("RatingController",["$scope","$attrs","$parse","ratingConfig",function(e,t,n,a){this.maxRange=angular.isDefined(t.max)?e.$parent.$eval(t.max):a.max,this.stateOn=angular.isDefined(t.stateOn)?e.$parent.$eval(t.stateOn):a.stateOn,this.stateOff=angular.isDefined(t.stateOff)?e.$parent.$eval(t.stateOff):a.stateOff,this.createDefaultRange=function(e){for(var t={stateOn:this.stateOn,stateOff:this.stateOff},n=Array(e),a=0;e>a;a++)n[a]=t;return n},this.normalizeRange=function(e){for(var t=0,n=e.length;n>t;t++)e[t].stateOn=e[t].stateOn||this.stateOn,e[t].stateOff=e[t].stateOff||this.stateOff;return e},e.range=angular.isDefined(t.ratingStates)?this.normalizeRange(angular.copy(e.$parent.$eval(t.ratingStates))):this.createDefaultRange(this.maxRange),e.rate=function(t){e.readonly||e.value===t||(e.value=t)},e.enter=function(t){e.readonly||(e.val=t),e.onHover({value:t})},e.reset=function(){e.val=angular.copy(e.value),e.onLeave()},e.$watch("value",function(t){e.val=t}),e.readonly=!1,t.readonly&&e.$parent.$watch(n(t.readonly),function(t){e.readonly=!!t})}]).directive("rating",function(){return{restrict:"EA",scope:{value:"=",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0}}),angular.module("ui.bootstrap.tabs",[]).directive("tabs",function(){return function(){throw Error("The `tabs` directive is deprecated, please migrate to `tabset`. Instructions can be found at http://github.com/angular-ui/bootstrap/tree/master/CHANGELOG.md")}}).controller("TabsetController",["$scope","$element",function(e){var t=this,n=t.tabs=e.tabs=[];t.select=function(e){angular.forEach(n,function(e){e.active=!1}),e.active=!0},t.addTab=function(e){n.push(e),(1===n.length||e.active)&&t.select(e)},t.removeTab=function(e){var a=n.indexOf(e);if(e.active&&n.length>1){var i=a==n.length-1?a-1:a+1;t.select(n[i])}n.splice(a,1)}}]).directive("tabset",function(){return{restrict:"EA",transclude:!0,replace:!0,require:"^tabset",scope:{},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",compile:function(e,t,n){return function(e,t,a,i){e.vertical=angular.isDefined(a.vertical)?e.$parent.$eval(a.vertical):!1,e.type=angular.isDefined(a.type)?e.$parent.$eval(a.type):"tabs",e.direction=angular.isDefined(a.direction)?e.$parent.$eval(a.direction):"top",e.tabsAbove="below"!=e.direction,i.$scope=e,i.$transcludeFn=n}}}}).directive("tab",["$parse","$http","$templateCache","$compile",function(e){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},compile:function(t,n,a){return function(t,n,i,r){var o,l;i.active?(o=e(i.active),l=o.assign,t.$parent.$watch(o,function(e){t.active=!!e}),t.active=o(t.$parent)):l=o=angular.noop,t.$watch("active",function(e){l(t.$parent,e),e?(r.select(t),t.onSelect()):t.onDeselect()}),t.disabled=!1,i.disabled&&t.$parent.$watch(e(i.disabled),function(e){t.disabled=!!e}),t.select=function(){t.disabled||(t.active=!0)},r.addTab(t),t.$on("$destroy",function(){r.removeTab(t)}),t.active&&l(t.$parent,!0),t.$transcludeFn=a}}}}]).directive("tabHeadingTransclude",[function(){return{restrict:"A",require:"^tab",link:function(e,t){e.$watch("headingElement",function(e){e&&(t.html(""),t.append(e))})}}}]).directive("tabContentTransclude",["$compile","$parse",function(){function e(e){return e.tagName&&(e.hasAttribute("tab-heading")||e.hasAttribute("data-tab-heading")||"tab-heading"===e.tagName.toLowerCase()||"data-tab-heading"===e.tagName.toLowerCase()) +}return{restrict:"A",require:"^tabset",link:function(t,n,a){var i=t.$eval(a.tabContentTransclude);i.$transcludeFn(i.$parent,function(t){angular.forEach(t,function(t){e(t)?i.headingElement=t:n.append(t)})})}}}]).directive("tabsetTitles",["$http",function(){return{restrict:"A",require:"^tabset",templateUrl:"template/tabs/tabset-titles.html",replace:!0,link:function(e,t,n,a){e.$eval(n.tabsetTitles)?a.$transcludeFn(a.$scope.$parent,function(e){t.append(e)}):t.remove()}}}]),angular.module("ui.bootstrap.timepicker",[]).constant("timepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:["AM","PM"],readonlyInput:!1,mousewheel:!0}).directive("timepicker",["$parse","$log","timepickerConfig",function(e,t,n){return{restrict:"EA",require:"?^ngModel",replace:!0,scope:{},templateUrl:"template/timepicker/timepicker.html",link:function(a,i,r,o){function l(){var e=parseInt(a.hours,10),t=a.showMeridian?e>0&&13>e:e>=0&&24>e;return t?(a.showMeridian&&(12===e&&(e=0),a.meridian===g[1]&&(e+=12)),e):void 0}function c(){var e=parseInt(a.minutes,10);return e>=0&&60>e?e:void 0}function s(e){return angular.isDefined(e)&&2>(""+e).length?"0"+e:e}function u(e){p(),o.$setViewValue(new Date(m)),d(e)}function p(){o.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function d(e){var t=m.getHours(),n=m.getMinutes();a.showMeridian&&(t=0===t||12===t?12:t%12),a.hours="h"===e?t:s(t),a.minutes="m"===e?n:s(n),a.meridian=12>m.getHours()?g[0]:g[1]}function f(e){var t=new Date(m.getTime()+6e4*e);m.setHours(t.getHours(),t.getMinutes()),u()}if(o){var m=new Date,g=n.meridians,h=n.hourStep;r.hourStep&&a.$parent.$watch(e(r.hourStep),function(e){h=parseInt(e,10)});var v=n.minuteStep;r.minuteStep&&a.$parent.$watch(e(r.minuteStep),function(e){v=parseInt(e,10)}),a.showMeridian=n.showMeridian,r.showMeridian&&a.$parent.$watch(e(r.showMeridian),function(e){if(a.showMeridian=!!e,o.$error.time){var t=l(),n=c();angular.isDefined(t)&&angular.isDefined(n)&&(m.setHours(t),u())}else d()});var $=i.find("input"),b=$.eq(0),y=$.eq(1),w=angular.isDefined(r.mousewheel)?a.$eval(r.mousewheel):n.mousewheel;if(w){var k=function(e){e.originalEvent&&(e=e.originalEvent);var t=e.wheelDelta?e.wheelDelta:-e.deltaY;return e.detail||t>0};b.bind("mousewheel wheel",function(e){a.$apply(k(e)?a.incrementHours():a.decrementHours()),e.preventDefault()}),y.bind("mousewheel wheel",function(e){a.$apply(k(e)?a.incrementMinutes():a.decrementMinutes()),e.preventDefault()})}if(a.readonlyInput=angular.isDefined(r.readonlyInput)?a.$eval(r.readonlyInput):n.readonlyInput,a.readonlyInput)a.updateHours=angular.noop,a.updateMinutes=angular.noop;else{var D=function(e,t){o.$setViewValue(null),o.$setValidity("time",!1),angular.isDefined(e)&&(a.invalidHours=e),angular.isDefined(t)&&(a.invalidMinutes=t)};a.updateHours=function(){var e=l();angular.isDefined(e)?(m.setHours(e),u("h")):D(!0)},b.bind("blur",function(){!a.validHours&&10>a.hours&&a.$apply(function(){a.hours=s(a.hours)})}),a.updateMinutes=function(){var e=c();angular.isDefined(e)?(m.setMinutes(e),u("m")):D(void 0,!0)},y.bind("blur",function(){!a.invalidMinutes&&10>a.minutes&&a.$apply(function(){a.minutes=s(a.minutes)})})}o.$render=function(){var e=o.$modelValue?new Date(o.$modelValue):null;isNaN(e)?(o.$setValidity("time",!1),t.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.')):(e&&(m=e),p(),d())},a.incrementHours=function(){f(60*h)},a.decrementHours=function(){f(60*-h)},a.incrementMinutes=function(){f(v)},a.decrementMinutes=function(){f(-v)},a.toggleMeridian=function(){f(720*(12>m.getHours()?1:-1))}}}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position","ui.bootstrap.bindHtml"]).factory("typeaheadParser",["$parse",function(e){var t=/^\s*(.*?)(?:\s+as\s+(.*?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+(.*)$/;return{parse:function(n){var a=n.match(t);if(!a)throw Error("Expected typeahead specification in form of '_modelValue_ (as _label_)? for _item_ in _collection_' but got '"+n+"'.");return{itemName:a[3],source:e(a[4]),viewMapper:e(a[2]||a[1]),modelMapper:e(a[1])}}}}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$position","typeaheadParser",function(e,t,n,a,i,r,o){var l=[9,13,27,38,40];return{require:"ngModel",link:function(c,s,u,p){var d=c.$eval(u.typeaheadMinLength)||1,f=c.$eval(u.typeaheadWaitMs)||0,m=c.$eval(u.typeaheadEditable)!==!1,g=t(u.typeaheadLoading).assign||angular.noop,h=t(u.typeaheadOnSelect),v=u.typeaheadInputFormatter?t(u.typeaheadInputFormatter):void 0,$=t(u.ngModel).assign,b=o.parse(u.typeahead),y=angular.element("");y.attr({matches:"matches",active:"activeIdx",select:"select(activeIdx)",query:"query",position:"position"}),angular.isDefined(u.typeaheadTemplateUrl)&&y.attr("template-url",u.typeaheadTemplateUrl);var w=c.$new();c.$on("$destroy",function(){w.$destroy()});var k=function(){w.matches=[],w.activeIdx=-1},D=function(e){var t={$viewValue:e};g(c,!0),n.when(b.source(w,t)).then(function(n){if(e===p.$viewValue){if(n.length>0){w.activeIdx=0,w.matches.length=0;for(var a=0;n.length>a;a++)t[b.itemName]=n[a],w.matches.push({label:b.viewMapper(w,t),model:n[a]});w.query=e,w.position=r.position(s),w.position.top=w.position.top+s.prop("offsetHeight")}else k();g(c,!1)}},function(){k(),g(c,!1)})};k(),w.query=void 0;var x;p.$parsers.unshift(function(e){return k(),e&&e.length>=d&&(f>0?(x&&a.cancel(x),x=a(function(){D(e)},f)):D(e)),m?e:(p.$setValidity("editable",!1),void 0)}),p.$formatters.push(function(e){var t,n,a={};return v?(a.$model=e,v(c,a)):(a[b.itemName]=e,t=b.viewMapper(c,a),a[b.itemName]=void 0,n=b.viewMapper(c,a),t!==n?t:e)}),w.select=function(e){var t,n,a={};a[b.itemName]=n=w.matches[e].model,t=b.modelMapper(c,a),$(c,t),p.$setValidity("editable",!0),h(c,{$item:n,$model:t,$label:b.viewMapper(c,a)}),k(),s[0].focus()},s.bind("keydown",function(e){0!==w.matches.length&&-1!==l.indexOf(e.which)&&(e.preventDefault(),40===e.which?(w.activeIdx=(w.activeIdx+1)%w.matches.length,w.$digest()):38===e.which?(w.activeIdx=(w.activeIdx?w.activeIdx:w.matches.length)-1,w.$digest()):13===e.which||9===e.which?w.$apply(function(){w.select(w.activeIdx)}):27===e.which&&(e.stopPropagation(),k(),w.$digest()))});var T=function(e){s[0]!==e.target&&(k(),w.$digest())};i.bind("click",T),c.$on("$destroy",function(){i.unbind("click",T)}),s.after(e(y)(w))}}}]).directive("typeaheadPopup",function(){return{restrict:"E",scope:{matches:"=",query:"=",active:"=",position:"=",select:"&"},replace:!0,templateUrl:"template/typeahead/typeahead-popup.html",link:function(e,t,n){e.templateUrl=n.templateUrl,e.isOpen=function(){return e.matches.length>0},e.isActive=function(t){return e.active==t},e.selectActive=function(t){e.active=t},e.selectMatch=function(t){e.select({activeIdx:t})}}}}).directive("typeaheadMatch",["$http","$templateCache","$compile","$parse",function(e,t,n,a){return{restrict:"E",scope:{index:"=",match:"=",query:"="},link:function(i,r,o){var l=a(o.templateUrl)(i.$parent)||"template/typeahead/typeahead-match.html";e.get(l,{cache:t}).success(function(e){r.replaceWith(n(e.trim())(i))})}}}]).filter("typeaheadHighlight",function(){function e(e){return e.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(t,n){return n?t.replace(RegExp(e(n),"gi"),"$&"):t}}); \ No newline at end of file