(function () {
    'use strict';

    function slideAnimation() {
        var addClassAnimation = function (element, className, done) {
            if (className === 'met-hide') {
                jQuery(element).slideUp(500, done);
            }
        }

        var removeClassAnimation = function (element, className, done) {
            if (className === 'met-hide') {
                jQuery(element).slideDown(500, done);
            }
        }

        return {
            addClass: addClassAnimation,
            removeClass: removeClassAnimation
        };
    }

    var oneKeyApp = angular.module('oneKeyApp',
        [
            'ngResource', 'ngSanitize', 'ui.bootstrap', 'taiPlaceholder', 'ngFileUpload', 'ngAnimate', 'ngAria',
            'datetimepicker', 'highcharts-ng', 'ngCookies', 'pascalprecht.translate', 'angular.chosen',
            'oneKeyApp.inventoryAdd', 'oneKeyApp.placeAdd', 'oneKeyApp.placeMigration', 'oneKeyApp.core',
            'ngMaterial', 'ngMessages', 'ui.router', 'ui.select', 'auth0.auth0', 'oneKeyApp.settings'
        ])
        // ui-router documentation: github.com/angular-ui/ui-router/wiki
        .config(function ($stateProvider, $urlRouterProvider, $locationProvider, angularAuth0Provider, appSettingsProvider) {
            var appSettings = appSettingsProvider.getSettings('appSettings');
            $locationProvider.html5Mode({
                enabled: true,
                requireBase: false,
                rewriteLinks: false
            });
            
            angularAuth0Provider.init({
                clientID: appSettings['auth0ClientId'],
                domain: appSettings['auth0Domain'],
                responseType: appSettings['auth0ResponseType'],
                redirectUri: window.location.origin + '/callback',
                scope: appSettings['auth0Scope'],
                audience: appSettings['auth0Audience']
            });
            $stateProvider
                .state('index',
                    {
                        url: '/'
                })
                .state('inventory',
                    {
                        url: '/inventory',
                        params: { success: null, removeFilters: null },
                        resolve: {
                            maintenance: 'maintenanceService',
                            successMessage: [
                                '$stateParams', function($stateParams) {
                                    return $stateParams.success;
                                }
                            ]
                        },
                        controller: function($stateParams, formModels, notify, maintenance) {
                            maintenance.getMaintenanceStatus()
                                .then(function(data) {
                                    var message = maintenance.parseMessage(data);
                                    if (message) {
                                        var id = 0; 
                                        if (data.scheduledMaintenance) {
                                            id = data.scheduledMaintenance.id;
                                        }
                                        maintenanceToast(message, id);
                                    }
                                });

                            var saveResponse = formModels.saveResponse;
                            if (saveResponse.isSuccess) {
                                notify.itemAdded(saveResponse.message);
                                saveResponse.isSuccess = false;
                            }


                            function maintenanceToast(message, messageId) {
                                toastr.options = {
                                    'closeButton': true,
                                    'closeClass': 'toast-close-button',
                                    'positionClass': 'toast-top-center',
                                    'toastClass': 'alert',
                                    'iconClass': 'alert-warning',
                                    'timeOut': 0,
                                    'tapToDismiss': true,
                                    'extended-timeOut': 0,
                                    'closeOnHover': false,
                                    'onHidden': function() {
                                        localStorage.setItem('shownMaintenanceMessage' + messageId, true);
                                    }
                                };
                                toastr['warning'](message);
                            }

                        }
                    })
                .state('add-options',
                    {
                        url: '/add-options',
                        template: '<add-inventory-landing-page></add-inventory-landing-page>',
                        resolve: {
                            model: function(addFormModel, formModels) {
                                addFormModel = formModels.cleanFormModel;
                                return addFormModel;
                            }
                        }
                    })
                .state('places',
                    {
                        url: '/places',
                        params: { successMigrationMessage: null, successMigration: null },
                        resolve: {
                            successMigrationMessage: [
                                '$stateParams', function($stateParams) {
                                    return $stateParams.successMigrationMessage;
                                }
                            ]
                        },
                        controller: function($stateParams, formModels, notify) {
                            if ($stateParams.successMigration) {
                                notify.itemAdded($stateParams.successMigrationMessage);
                            }
                        }
                    })
                .state('add-place',
                    {
                        url: '/add-place',
                        templateUrl: 'custom-modules/add-place/templates/addPlaceForm.html',
                        controller: 'PlaceAddCtrl',
                        controllerAs: 'paCtrl',
                        params: { placeType: null }
                    })
                .state('place-migration',
                    {
                        url: '/place-migration',
                        template: '<place-migration-landing-page></place-migration-landing-page>',
                        resolve: {
                            model: function(formModels) {
                                return formModels.cleanFormModel;
                            }
                        }
                    })
                .state('add-place-options',
                    {
                        url: '/add-place-options',
                        template: '<add-place-landing-page></add-place-landing-page>',
                        resolve: {
                            model: function(formModels) {
                                return formModels.cleanFormModel;
                            }
                        }
                    })
                .state('search',
                    {
                        url: '/search',
                        templateUrl: 'custom-modules/add-inventory/templates/milwaukee-search.html',
                        controller: 'searchController',
                        controllerAs: 'searchCtrl',
                        resolve: {
                            model: function(addFormModel) {
                                addFormModel.kit = {};
                                return addFormModel;
                            }
                        },
                        params: { fromState: null, manufacturer: null }
                    })
                .state('existing',
                    {
                        url: '/existing',
                        template: '<met-existing-search></met-existing-search>',
                        params: { fromState: null, manufacturer: null, productId: null }
                    })
                .state('add-new',
                    {
                        url: '/add-new',
                        templateUrl: 'custom-modules/add-inventory/templates/addForm.html',
                        controller: 'InventoryAddCtrl',
                        controllerAs: 'iaCtrl',
                        params: {
                            fromState: null,
                            manufacturer: null,
                            productId: null,
                            showForm: true,
                            selectedIndex: null
                        }
                    })
                .state('upload',
                    {
                        url: '/upload',
                        templateUrl: 'custom-modules/add-inventory/templates/upload.html'
                });
        })
        .config([
            '$modalProvider',
            function ($modalProvider) {
                $modalProvider.defaultContainer = angular.element(document).find('#onekey').eq(0);
            }
        ])
        .config([
            '$httpProvider', function ($httpProvider) {
                if (localStorage.getItem('access_token')) {
                    $httpProvider.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('access_token');
                }

                var $cookies;
                angular.injector(['ngCookies'])
                    .invoke([
                        '$cookies',
                        function ($cookiestemp) {
                            $cookies = $cookiestemp;
                        }
                    ]);

                $httpProvider.defaults.headers.common['Accept-Language'] = $cookies['language'];
            }
        ])
        .config([
            '$mdThemingProvider', function ($mdThemingProvider) {
                $mdThemingProvider.definePalette('mketred',
                    {
                        '50': 'fbe1e4',
                        '100': 'f4b3bb',
                        '200': 'ed808e',
                        '300': 'e64d60',
                        '400': 'e0273e',
                        '500': 'db011c',
                        '600': 'd70119',
                        '700': 'd20114',
                        '800': 'cd0111',
                        '900': 'c40009',
                        'A100': 'ffeced',
                        'A200': 'ffb9ba',
                        'A400': 'ff8688',
                        'A700': 'ff6d6f',
                        'contrastDefaultColor': 'light',
                        'contrastDarkColors': [
                            '50',
                            '100',
                            '200',
                            'A100',
                            'A200',
                            'A400',
                            'A700'
                        ],
                        'contrastLightColors': [
                            '300',
                            '400',
                            '500',
                            '600',
                            '700',
                            '800',
                            '900'
                        ]
                    });
                $mdThemingProvider.definePalette('mketactionblue',
                    {
                        '50': 'e1edfc',
                        '100': 'b5d2f8',
                        '200': '83b5f3',
                        '300': '5197ee',
                        '400': '2c80ea',
                        '500': '076ae6',
                        '600': '0662e3',
                        '700': '0557df',
                        '800': '044ddb',
                        '900': '023cd5',
                        'A100': 'fcfdff',
                        'A200': 'c9d5ff',
                        'A400': '96adff',
                        'A700': '7d99ff',
                        'contrastDefaultColor': 'light',
                        'contrastDarkColors': [
                            '50',
                            '100',
                            '200',
                            '300',
                            'A100',
                            'A200',
                            'A400',
                            'A700'
                        ],
                        'contrastLightColors': [
                            '400',
                            '500',
                            '600',
                            '700',
                            '800',
                            '900'
                        ]
                    });
                $mdThemingProvider.definePalette('mketFeaturePurple',
                    {
                        '50': 'e8e9ee',
                        '100': 'c5c9d5',
                        '200': '9fa5ba',
                        '300': '79809e',
                        '400': '5c6589',
                        '500': '3f4a74',
                        '600': '39436c',
                        '700': '313a61',
                        '800': '293257',
                        '900': '1b2244',
                        'A100': '8599ff',
                        'A200': '526eff',
                        'A400': '1f44ff',
                        'A700': '062eff',
                        'contrastDefaultColor': 'light',
                        'contrastDarkColors': [
                            '50',
                            '100',
                            '200',
                            '300',
                            'A100'
                        ],
                        'contrastLightColors': [
                            '400',
                            '500',
                            '600',
                            '700',
                            '800',
                            '900',
                            'A200',
                            'A400',
                            'A700'
                        ]
                    });
                $mdThemingProvider.theme('mket')
                    .primaryPalette('mketred')
                    .accentPalette('mketactionblue');
            }
        ])
        .constant('maskOverlay',
            {
                fadeIn: function () {
                    var that = this;
                    $('#mask-overlay').fadeIn(100);
                    $('#mask-overlay').click(function () { that.fadeOut(); });
                },
                fadeOut: function () {
                    $('#mask-overlay').fadeOut(100);
                    $("#mask-overlay").unbind("click");
                }
            })
        .constant('settings',
            {
                dateFormats: {
                    date: function (isDisplay) {
                        var $cookies;
                        angular.injector(['ngCookies']).invoke([
                            '$cookies', function ($cookiestemp) {
                                $cookies = $cookiestemp;
                            }
                        ]);

                        var format = isDisplay ? "dd/MM/yyyy" : "DD/MM/YYYY";
                        if ($cookies.language === "en-US") {
                            format = isDisplay ? "MM/dd/yyyy" : "MM/DD/YYYY";
                        }

                        if ($cookies.language !== undefined) {
                            if ($cookies.language === "pl-PL" || $cookies.language === "sv-SE") {
                                format = isDisplay ? "yyyy/MM/dd" : "YYYY/MM/DD";
                            }

                            if ($cookies.language.match(/^hu-HU|lt-LT$/)) {
                                format = isDisplay ? "yyyy/MM/dd" : "YYYY/MM/DD";
                            }
                        }

                        return format;
                    },
                    dateTime: function (isDisplay) {
                        var dateFormat = this.date(isDisplay);
                        return dateFormat + ' - H:mm:ss';
                    },
                    shortDateTime: function (isDisplay) {
                        var dateFormat = this.date(isDisplay);
                        return dateFormat + ' h:mm a';
                    },
                    api: 'YYYY-MM-DDThh:mm:ss.SSS',
                    getDatePickerOptions: function () {
                        var $cookies;
                        angular.injector(['ngCookies']).invoke([
                            '$cookies', function ($cookiestemp) {
                                $cookies = $cookiestemp;
                            }
                        ]);
                        var locale = $cookies.language;
                        var format = this.date(false);
                        return {
                            format: format,
                            debug: false,
                            widgetPositioning: { horizontal: 'left', vertical: 'bottom' },
                            locale: locale
                        };
                    }
                }
            })
        .filter('propsFilter',
            function () {
                return function (items, props) {
                    var out = [];

                    if (angular.isArray(items)) {
                        var keys = Object.keys(props);

                        items.forEach(function (item) {
                            var itemMatches = false;

                            for (var i = 0; i < keys.length; i++) {
                                var prop = keys[i];
                                var text = props[prop].toLowerCase();
                                if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
                                    itemMatches = true;
                                    break;
                                }
                            }

                            if (itemMatches) {
                                out.push(item);
                            }
                        });
                    }
                    else {
                        out = items;
                    }

                    return out;
                };
            })
        .animation(".slide-animation", slideAnimation)
        .factory('jstz',
            [
                '$window', function ($window) {
                    return $window.jstz;
                }
            ])
        .constant('host',
            {
                getCurrentHost: function () {
                    var segs = location.host.split('.');
                    return segs[_.findLastIndex(segs)];
                },
                isEMEA: function () {
                    return this.getCurrentHost() === 'eu';
                },
                isNA: function () {
                    return this.getCurrentHost() === 'com';
                },
                isANZ: function () {
                    return this.getCurrentHost() === 'au' || this.getCurrentHost() === 'nz';
                },
                languageSegment: function () {
                    var segs = location.host.split('.');
                    return segs[1];
                }
            })
        .run(function ($rootScope, $stateParams, authService) {
           authService.handleAuthentication();
            $rootScope.$on('$stateChangeStart',
                function (event, toState, toParams, fromState) {
                    var retainFilters = sessionStorage.getItem('retainFilters');
                    var user = sessionStorage.getItem('user');
                    if (user !== document.auth) {
                        $stateParams.clearFilters = true;
                        sessionStorage.setItem('user', document.auth);
                    }
                    if (!retainFilters) {
                        $stateParams.clearFilters = true;
                        sessionStorage.setItem('retainFilters', true);
                    }
                    if (fromState.name === 'search' && toParams.fromState === null) {
                        toParams.blankForm = true;
                    }
                    if (fromState.name === 'existing' && toParams.fromState === null) {
                        toParams.blankForm = true;
                    }
                    if (fromState.name === '' && toState.name === 'add-new') {
                        toParams.redirect = true;
                    }

                    //console.log(toParams); // uncomment to debug $state parameters 
                });
        });
}());

angular.module('oneKeyApp').run(['$templateCache', function($templateCache) {$templateCache.put('categories/categoriesAssign.html','<div id=onekey-modal data-ng-init=initialize()><div class=modal-spinner data-ng-show=saving><i class="fa fa-spinner fa-spin"></i></div><div class=modal-header><h3 class=modal-title>{{ messages.editCategory.value }}</h3></div><div class=modal-body><ul class="nav nav-tabs" role=tablist><li data-ng-class="!addMode && \'active\'"><a href role=tab data-ng-click="addMode = false">{{messages.select.value}}</a></li><li data-ng-class="addMode && \'active\'"><a href role=tab data-ng-click="addMode = true">{{messages.addNew.value}}</a></li></ul><div class=tab-content><form novalidate name=editForm data-ng-hide=addMode><div class=form-group data-ng-class="{\'has-error\':!editValid}"><label class=control-label for=categoryName>{{ messages.category.value }} *</label><met-category-selector name=categoryName data-ng-model=selectedCategory data-met-categories=categories data-met-exclude-add-option=true data-met-include-placeholder=true></met-category-selector><p data-ng-show=!editValid class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ editError }}</p></div></form><form novalidate name=addForm data-ng-show=addMode><div class=form-group data-ng-class="{\'has-error\':!addValid}"><label class=control-label for=categoryName>{{ messages.categoryTitle.value }} *</label> <input type=text id=categoryName name=categoryName class=form-control required data-ng-model=category.categoryName data-met-focus-on=loaded maxlength=64 tabindex=10 data-met-enter=add()><p data-ng-show=!addValid class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ addError }}</p></div><div class=form-group data-ng-class="{\'has-error\':!valid}"><label class=control-label>{{messages.parentCategoryTitle.value}}</label><met-category-selector name=categoryId data-ng-model=category.parentCategory data-met-categories=parentCategories data-met-include-placeholder=true data-met-exclude-add-option=true></met-category-selector></div></form></div></div><div class=modal-footer><button type=button class="btn btn-action-black" tabindex=11 data-ng-click=cancel()>{{ messages.cancel.value }}</button> <button type=submit class="btn btn-action-red" tabindex=12 data-ng-hide=addMode data-ng-click=edit() data-ng-disabled=saving data-ng-class="{\'disabled\':saving}">{{ messages.save.value }}</button> <button type=submit class="btn btn-action-red" tabindex=12 data-ng-show=addMode data-ng-click=add() data-ng-disabled=saving data-ng-class="{\'disabled\':saving}">{{ messages.save.value }}</button></div></div>');
$templateCache.put('directives/geofence.directive.html','<div><h1>Geofence</h1><div id=floating-panel><input id=delete-button type=button value="Clear Map" ng-click=deleteSelectedShape()> <input id=load-geofence type=button value="Load MPBID" ng-click=load()> <label>MPBID</label> <input id=mpbid type=text ng-model=mpbid> <label>Email</label> <input id=email type=email ng-model=email> <input id=save-geofence type=button value=Save ng-click=save()></div><div><div id=map_canvas style="border: 2px solid #3872ac;"></div><div id=geofenceLogs style="padding: 15px; width:100%;" data-ng-if="logs.length > 0"><h2>Logs</h2><table style="border-collapse: collapse"><thead><tr><th class=geofence-table-cells>Geofence</th><th class=geofence-table-cells>Lat</th><th class=geofence-table-cells>Lng</th><th class=geofence-table-cells>GPS Quality</th><th class=geofence-table-cells>Last Seen</th></tr></thead><tbody><tr data-ng-repeat="log in logs"><td class=geofence-table-cells>{{log.brokeFence ? \'Left\': \'Entered\'}}</td><td class=geofence-table-cells>{{log.event.latitude}}</td><td class=geofence-table-cells>{{log.event.longitude}}</td><td class=geofence-table-cells>{{log.event.quality}}</td><td class=geofence-table-cells>{{log.event.lastSeen}}</td></tr></tbody></table></div></div></div>');
$templateCache.put('images/imagesAssign.html','<div id=onekey-modal><div class=modal-spinner data-ng-show=saving><i class="fa fa-spinner fa-spin"></i></div><div class=modal-header><h3 class=modal-title>{{messages.editImage.value}}</h3></div><div class=modal-body><div class="tab-content image-assign"><form novalidate name=editForm><div class=form-group data-ng-class="{\'has-error\':!valid}"><label class=control-label for=imageUrl>{{messages.imageUrl.value}} *</label><met-file-uploader data-ng-model=imageUrl data-met-model-alternates=imageAlternates data-met-upload-url={{urls.imageUploadUrl}} data-met-on-file-uploaded=onFileUploaded data-met-image-detail-position=right data-met-show-thumb></met-file-uploader><p data-ng-show=!valid class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{error}}</p></div></form></div></div><div class=modal-footer><button type=button class="btn btn-action-black" tabindex=11 data-ng-click=cancel()>{{messages.cancel.value}}</button> <button type=submit class="btn btn-action-red" tabindex=12 data-ng-click=save() data-ng-disabled=saving data-ng-class="{\'disabled\':saving}">{{messages.save.value}}</button></div></div>');
$templateCache.put('newFeatureCarousel/newFeaturesCarouselModal.html','<md-dialog class=new-feature-dialog aria-label=messages.wereAddingNewFeatures.value style="width: 60%; height: 500px;"><md-dialog-content class=new-feature-content><form ng-cloak><div class=close-button-container><md-button class=md-icon-button aria-label=close ng-click=cancel()><i class=icon-cross></i></md-button></div><div class=new-feature-titles><h3>{{messages.whatsNew.value}}</h3><h4>{{messages.wereAddingNewFeatures.value}}</h4></div><div id=myCarousel class="carousel slide" data-ride=carousel data-interval=10000><ol class=carousel-indicators><li data-target=#myCarousel data-slide-to=0 class=active></li><li data-target=#myCarousel data-slide-to=1></li><li data-target=#myCarousel data-slide-to=2></li></ol><div class=carousel-inner><div class="item active new-feature-dialog-text"><i class="icon icon-radar new-feature-icon"></i><div>{{messages.geofencingBetaTitle.value}}</div><div>{{messages.geofencingBetaSubTitle.value}}</div></div><div class="item new-feature-dialog-text"><i class="icon icon-chart-bars new-feature-icon"></i><div>{{messages.geofencingInOutTitle.value}}</div><div>{{messages.geofencingInOutSubTitle.value}}</div></div><div class="item new-feature-dialog-text"><i class="icon icon-clipboard-text new-feature-icon"></i><div>{{messages.geofencingDailyNotificationTitle.value}}</div><div>{{messages.geofencingDailyNotificationSubTitle.value}}</div></div></div><a class="left carousel-control" href=#myCarousel data-slide=prev><span class="icon icon-chevron-left-circle"></span> <span class=sr-only>Previous</span></a> <a class="right carousel-control" href=#myCarousel data-slide=next><span class="icon icon-chevron-right-circle"></span> <span class=sr-only>Next</span></a></div></form></md-dialog-content></md-dialog>');
$templateCache.put('people/messages.html','<div ng-message=required><i class="icon icon-warning"></i>&nbsp;This field is required.</div><div ng-message=maxlength><i class="icon icon-warning"></i>&nbsp;This field is too long.</div><div ng-message=!new.valid><i class="icon icon-warning"></i>&nbsp;A Person with that name already exists.</div>');
$templateCache.put('people/peopleAssign.html','<div id=onekey-modal data-ng-init=initialize()><div class=modal-spinner data-ng-show=saving><i class="fa fa-spinner fa-spin"></i></div><div class=modal-header><h3 class=modal-title>{{ messages.editPerson.value }}</h3></div><div class=modal-body><ul class="nav nav-tabs" role=tablist><li data-ng-class="!addMode && \'active\'"><a href role=tab data-ng-click="addMode = false">{{messages.select.value}}</a></li><li data-ng-class="addMode && \'active\'"><a href role=tab data-ng-click="addMode = true">{{messages.addNew.value}}</a></li></ul><div class=tab-content><form novalidate name=editForm data-ng-hide=addMode><div class=form-group data-ng-class="{\'has-error\':!editValid}"><label class=control-label for=personName>{{ messages.person.value }} *</label><met-person-selector name=personName data-ng-model=selectedPerson data-met-people=people data-met-exclude-add-option=true data-met-include-placeholder=true></met-person-selector><p data-ng-show=!editValid class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ editError }}</p></div></form><form novalidate name=addForm data-ng-show=addMode><div class=form-group data-ng-class="{\'has-error\':!addValid}"><label class=control-label for=personName>{{ messages.personTitle.value }} *</label> <input type=text id=personName name=personName class=form-control required data-ng-model=person.personName data-met-focus-on=loaded maxlength=64 tabindex=10 data-met-enter=add()><p data-ng-show=!addValid class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ addError }}</p></div></form></div></div><div class=modal-footer><button type=button class="btn btn-action-black" tabindex=11 data-ng-click=cancel()>{{ messages.cancel.value }}</button> <button type=submit class="btn btn-action-red" tabindex=12 data-ng-hide=addMode data-ng-click=edit() data-ng-disabled=saving data-ng-class="{\'disabled\':saving}">{{ messages.save.value }}</button> <button type=submit class="btn btn-action-red" tabindex=12 data-ng-show=addMode data-ng-click=add() data-ng-disabled=saving data-ng-class="{\'disabled\':saving}">{{ messages.save.value }}</button></div></div>');
$templateCache.put('reports/metCrimperSummary.directive.html','<div class=row><div class=col-md-4><aside class=report-summary><img src=/Content/images/crimper-dashboard-crimper.png><h2>{{totalEvents | number:0}}</h2><h1>{{messages.totalCycles.value}}</h1></aside></div><div class=col-md-4><aside class=report-summary><img src=/Content/images/crimper-dashboard-checkmark.png><h2>{{successfulEvents | number:0}}</h2><h1>{{messages.fullPressureCycles.value}}</h1></aside></div><div class=col-md-4><aside class=report-summary><img src=/Content/images/crimper-dashboard-percentage.png><h2>{{successRate}}</h2><h1>{{messages.fullPressureRate.value}}</h1></aside></div></div>');
$templateCache.put('statuses/statusesAssign.html','<div id=onekey-modal><div class=modal-spinner data-ng-show=saving><i class="fa fa-spinner fa-spin"></i></div><div class=modal-header><h3 class=modal-title>{{messages.editStatus.value}}</h3></div><div class=modal-body><div class=tab-content><form novalidate name=editForm><div class=form-group data-ng-class="{\'has-error\':!valid}"><label class=control-label for=status>{{messages.status.value}} *</label><select name=status class=form-control data-ng-model=status data-ng-options="s.description for s in statuses track by s.id" data-met-select-placeholder></select><p data-ng-show=!valid class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{error}}</p></div></form></div></div><div class=modal-footer><button type=button class="btn btn-action-black" tabindex=11 data-ng-click=cancel()>{{messages.cancel.value}}</button> <button type=submit class="btn btn-action-red" tabindex=12 data-ng-click=save() data-ng-disabled=saving data-ng-class="{\'disabled\':saving}">{{messages.save.value}}</button></div></div>');
$templateCache.put('trades/tradesAssign.html','<div id=onekey-modal data-ng-init=initialize()><div class=modal-spinner data-ng-show=saving><i class="fa fa-spinner fa-spin"></i></div><div class=modal-header><h3 class=modal-title>{{ messages.editDivision.value }}</h3></div><div class=modal-body><ul class="nav nav-tabs" role=tablist><li data-ng-class="!addMode && \'active\'"><a href role=tab data-ng-click="addMode = false">{{messages.select.value}}</a></li><li data-ng-class="addMode && \'active\'"><a href role=tab data-ng-click="addMode = true">{{messages.addNew.value}}</a></li></ul><div class=tab-content><form novalidate name=editForm data-ng-hide=addMode><div class=form-group data-ng-class="{\'has-error\':!editValid}"><label class=control-label for=tradeName>{{ messages.division.value }} *</label><met-trade-selector name=tradeName data-ng-model=selectedTrade data-met-trades=trades data-met-exclude-add-option=true data-met-include-placeholder=true></met-trade-selector><p data-ng-show=!editValid class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ editError }}</p></div></form><form novalidate name=addForm data-ng-show=addMode><div class=form-group data-ng-class="{\'has-error\':!addValid}"><label class=control-label for=tradeName>{{ messages.divisionTitle.value }} *</label> <input type=text id=tradeName name=tradeName class=form-control required data-ng-model=trade.tradeName data-met-focus-on=loaded maxlength=64 tabindex=10 data-met-enter=add()><p data-ng-show=!addValid class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ addError }}</p></div></form></div></div><div class=modal-footer><button type=button class="btn btn-action-black" tabindex=11 data-ng-click=cancel()>{{ messages.cancel.value }}</button> <button type=submit class="btn btn-action-red" tabindex=12 data-ng-hide=addMode data-ng-click=edit() data-ng-disabled=saving data-ng-class="{\'disabled\':saving}">{{ messages.save.value }}</button> <button type=submit class="btn btn-action-red" tabindex=12 data-ng-show=addMode data-ng-click=add() data-ng-disabled=saving data-ng-class="{\'disabled\':saving}">{{ messages.save.value }}</button></div></div>');
$templateCache.put('directives/categories/categoriesAdd.html','<div id=onekey-add-object-dialog><div class=modal-spinner data-ng-show=saving><i class="fa fa-spinner fa-spin"></i></div><form novalidate name=addForm data-ng-submit=save(addForm)><div class=modal-header><h3 class=modal-title>{{messages.addCategory.value}}</h3></div><div class=modal-body><div class=form-group data-ng-class="{\'has-error\': !valid}"><label class=control-label for=categoryName>{{messages.categoryTitle.value}} *</label> <input type=text id=categoryName name=categoryName class=form-control required data-ng-model=category.categoryName data-met-focus-on=loaded maxlength=64 tabindex=10 data-met-enter=save(addForm) ng-change=clearError()><p data-ng-if=duplicate class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ error }}</p></div><div id=onekey-add-object-dialog_parent-category-selector class=form-group><label class=control-label>{{messages.parentCategoryTitle.value}}</label><met-category-selector name=categoryId data-ng-model=category.parentCategory data-met-categories=categories data-met-include-placeholder=true data-met-exclude-add-option=true></met-category-selector></div></div></form><div class=modal-footer><button type=button class="btn btn-action-black" tabindex=11 data-ng-click=cancel()>{{messages.cancel.value}}</button> <button type=submit class="btn btn-action-blue" tabindex=12 data-ng-click=save()>{{messages.save.value}}</button></div></div>');
$templateCache.put('directives/locations/locationsAdd.html','<div id=onekey-add-object-dialog><div class=modal-spinner data-ng-show=saving><i class="fa fa-spinner fa-spin"></i></div><form novalidate name=addForm data-ng-submit=save(addForm)><div class=modal-header><h3 class=modal-title>{{messages.addLocation.value}}</h3></div><div class=modal-body><div class=form-group data-ng-class="{\'has-error\':!valid}"><label class=control-label for=locationName>{{messages.locationTitle.value}} *</label> <input type=text id=locationName name=locationName class=form-control required data-ng-model=location.locationName data-met-focus-on=loaded maxlength=64 tabindex=10 data-met-enter=save(addForm) ng-change=clearError()><p data-ng-if=duplicate class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ error }}</p></div><div class=form-group><label class=control-label for=productNumber>{{messages.jobNumber.value}}</label> <input type=text id=productNumber name=productNumber class=form-control data-ng-model=location.productNumber maxlength=100 tabindex=10 data-met-enter=save(addForm)></div></div><div class=modal-footer><button type=button class="btn btn-action-black" tabindex=11 data-ng-click=cancel()>{{messages.cancel.value}}</button> <button type=submit class="btn btn-action-blue" tabindex=12>{{messages.save.value}}</button></div></form></div>');
$templateCache.put('directives/Manufacturers/manufacturersAdd.html','<div id=onekey-add-object-dialog><div class=modal-spinner data-ng-show=saving><i class="fa fa-spinner fa-spin"></i></div><form novalidate name=addForm data-ng-submit=save(addForm)><div class=modal-header><h3 class=modal-title>{{messages.addManufacturer.value}}</h3></div><div class=modal-body><div class=form-group data-ng-class="{\'has-error\':!valid}"><label class=control-label for=manufacturerName>{{messages.manufacturerTitle.value}} *</label> <input type=text id=manufacturerName name=manufacturerName class=form-control required data-ng-model=manufacturer.manufacturerName data-met-focus-on=loaded maxlength=64 tabindex=10 data-met-enter=save(addForm) ng-change=clearError()><p data-ng-if=duplicate class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ error }}</p></div></div><div class=modal-footer><button type=button class="btn btn-action-black" tabindex=11 data-ng-click=cancel()>{{messages.cancel.value}}</button> <button type=submit class="btn btn-action-blue" tabindex=12>{{messages.save.value}}</button></div></form></div>');
$templateCache.put('directives/persons/peopleAdd.html','<div id=onekey-add-object-dialog><div class=modal-spinner data-ng-show=saving><i class="fa fa-spinner fa-spin"></i></div><form novalidate name=addForm data-ng-submit=save(addForm)><div class=modal-header><h3 class=modal-title>{{messages.addPerson.value}}</h3></div><div class=modal-body><div class=form-group data-ng-class="{\'has-error\':!valid}"><label class=control-label for=personName>{{messages.personTitle.value}} *</label> <input type=text id=personName name=personName class=form-control required data-ng-model=person.personName data-met-focus-on=loaded maxlength=64 tabindex=10 data-met-enter=save(addForm) ng-change=clearError()><div ng-messages=profileForm.personName.$error><p data-ng-if=duplicate class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ error }}</p></div></div></div><div class=modal-footer><button type=button class="btn btn-action-black" tabindex=11 data-ng-click=cancel()>{{messages.cancel.value}}</button> <button type=submit class="btn btn-action-blue" tabindex=12>{{messages.save.value}}</button></div></form></div>');
$templateCache.put('directives/places/metAlertCantDrawGeofence.html','<md-dialog aria-label={{messages.cantDrawFence.value}}><form ng-cloak><md-dialog-content><p class=bold>{{messages.cantDrawFence.value}}</p><p>{{messages.cantDrawFenceMessage.value}}</p><div class=action-buttons><md-button class=met-flat-button ng-click="answer(\'ok\')">{{ messages.ok.value }}</md-button></div></md-dialog-content></form></md-dialog>');
$templateCache.put('directives/places/metAlertCantMoveGeofence.html','<md-dialog aria-label={{messages.cantMovePin.value}}><form ng-cloak><md-dialog-content><p class=bold>{{messages.cantMovePin.value}}</p><p>{{messages.cantMovePinMessage.value}}</p><div class=action-buttons><md-button class=met-flat-button ng-click="answer(\'ok\')">{{ messages.ok.value }}</md-button></div></md-dialog-content></form></md-dialog>');
$templateCache.put('directives/places/metAlertGeofenceRemoval.html','<md-dialog aria-label={{messages.removeSetLocation.value}}><form ng-cloak><md-dialog-content><p class=bold>{{messages.removeSetLocation.value}}</p><p>{{messages.removeLocationMessage.value}}</p><div class=action-buttons><md-button class=met-flat-button ng-click="answer(\'cancel\')">{{ messages.cancel.value }}</md-button><md-button class=met-flat-button ng-click="answer(\'remove\')">{{ messages.remove.value }}</md-button></div></md-dialog-content></form></md-dialog>');
$templateCache.put('directives/places/metConfirmAddPerson.html','<md-dialog aria-label=messages.add.value><form ng-cloak><md-dialog-content><p class=bold>{{messages.add.value}} {{newPersonName}}</p><p>{{messages.personWillBeAdded.value}} {{place.placeName}}</p><div class=action-buttons><md-button class=met-flat-button ng-click="answer(\'cancel\')">{{ messages.cancel.value }}</md-button><md-button class=met-flat-button ng-click="answer(\'continue\')">{{ messages.continue.value }}</md-button></div></md-dialog-content></form></md-dialog>');
$templateCache.put('directives/places/metConfirmDeletePlace.html','<md-dialog aria-label=messages.deletePlaceConfirmation.value><form ng-cloak><md-dialog-content><h4 class=bold>{{messages.deletePlaceConfirmation.value}}</h4><p>{{messages.deletePlaceMessage_Corrected.value}}</p><div class=action-buttons><md-button class=met-flat-button ng-click=cancel()>{{ messages.cancel.value }}</md-button><md-button class=met-flat-button ng-click="answer(\'delete\')">{{ messages.delete.value }}</md-button></div></md-dialog-content></form></md-dialog>');
$templateCache.put('directives/places/metConfirmDuplicateName.html','<md-dialog aria-label=messages.add.value><form ng-cloak><md-dialog-content><p class=bold>{{newPersonName}} {{messages.alreadyExists.value}}</p><p>{{messages.assignExistingPerson.value}}</p><div class=action-buttons><md-button class=met-flat-button ng-click="answer(\'cancel\')">{{ messages.cancel.value }}</md-button><md-button class=met-flat-button ng-click="answer(\'assign\')">{{ messages.assign.value }}</md-button></div></md-dialog-content></form></md-dialog>');
$templateCache.put('directives/places/metEditPersonName.html','<md-dialog aria-label=messages.editName.value><form name=editNameForm ng-cloak><md-dialog-content><h4>{{messages.editName.value}}</h4><md-input-container id=container_{{place.placeId}}_{{personModel.personId}}><label>{{messages.name.value}}</label> <input id=name_{{place.placeId}}_{{personModel.personId}} required name=name data-ng-model=personModel.personName><div data-ng-messages=editNameForm.name.$error><div data-ng-message=required>{{messages.required.value}}</div></div></md-input-container><div data-ng-show=duplicate id=duplicate_{{place.placeId}}_{{personModel.personId}}>{{messages.name.value}} {{messages.alreadyExists.value}}</div><div class=action-buttons><md-button class=met-flat-button ng-click="answer(\'cancel\')">{{ messages.cancel.value }}</md-button><md-button class=met-flat-button ng-disabled="editNameForm.$invalid || duplicate" ng-click="answer(\'save\')">{{ messages.save.value }}</md-button></div></md-dialog-content></form></md-dialog>');
$templateCache.put('directives/places/metInventoryOverTimeByPlace.directive.html','<div class=tbc-place-graph data-ng-cloak><div class=date-range><label for=dateFrom class=range-text>{{messages.from.value}}</label> <input class=range-text id=dateFrom type=text data-ng-model=chartDateRange.start data-met-enter=dateChange()> <label for=dateTo class=range-text>{{messages.to.value}}</label> <input class=range-text id=dateTo type=text data-ng-model=chartDateRange.end data-met-enter=dateChange()></div><div id=inventoryOverTimeByPlaceChartContainer_{{place.placeId}}></div></div>');
$templateCache.put('directives/places/metPlace.directive.html','<div><md-whiteframe data-ng-click=expandPlace() id=place_{{place.placeId}} data-place-id={{place.placeId}} class="md-whiteframe-z1 place animate-element" layout layout-align="start center"><div class=place-type><img data-ng-if=place.imageUrl data-ng-src={{place.imageUrl}}><div class=type-icon-box data-ng-if="!place.imageUrl && place.typeId === 1"><md-icon class="type-icon icon-clipboard-alert" aria-label="messages.placeType_Unspecified.value messages.icon.value"></md-icon></div><div data-ng-if="!place.imageUrl && place.typeId === 2" class=type-icon-box><md-icon class="type-icon icon-city" aria-label="messages.homeBase.value messages.icon.value"></md-icon></div><div data-ng-if="!place.imageUrl && place.typeId === 3" class=type-icon-box><md-icon class="type-icon icon-home" aria-label="messages.projectJob.value messages.icon.value"></md-icon></div><div data-ng-if="!place.imageUrl && place.typeId === 4" class=type-icon-box><md-icon class="type-icon icon-truck" aria-label="messages.vehicle.value messages.icon.value"></md-icon></div></div><div class=place-name><span>{{place.placeName}}</span></div><div class="place-item sorted"><span>{{place.jobNumber}}</span></div><div class=place-item><span>{{place.division.divisionName}}</span></div><div class=place-item-centered><span>{{place.itemCount}}</span></div><div class=place-item-centered><span>{{place.peopleCount}}</span></div><div class=place-item-centered><span>{{place.needsActionToolCount}}</span></div><div class=place-address><span>{{place.startingAddressLine}}</span><br><span>{{place.startingCityStateZip}}</span></div><div class=standard-box-pad><i class=icon ng-class="place.isExpanded ? \'icon-chevron-up\' : \'icon-chevron-down\'"></i></div></md-whiteframe><div data-ng-cloak class="place-detail-container slide-animation" id=place-detail_{{place.placeId}} data-ng-class="{\'met-hide\' : !place.isExpanded}"><div class=place-details><div class=place-info><div class=place-info-detail><div class=place-imagery-container><div data-ng-if="place.typeId !== 4" md-theme=mket><div class=image-box data-ng-if=place.latitude><met-place-location-mini place-model=place class=mini-map></met-place-location-mini></div><div class="image-box empty" data-ng-if=!place.latitude><i class="icon icon-home" data-ng-if="place.typeId === 3"></i> <i class="icon icon-city" data-ng-if="place.typeId === 2"></i></div><div class=caption-box data-ng-if=place.latitude><span data-ng-if=place.addressLine>{{place.addressLine}}</span> <span data-ng-if=place.cityStateZip>{{place.cityStateZip}}</span> <span data-ng-if=!place.addressLine>{{messages.clickHereToAddALocation.value}}</span></div><div class="caption-box add-location-message" data-ng-if=!place.latitude><span>{{messages.clickHereToAddALocation.value}}</span></div><md-button data-ng-if=!place.latitude aria-label={{messages.editLocation.value}} class="md-mini md-fab" data-ng-click=toggleEditLocation() title={{messages.addLocationToolTip.value}}><i class="icon icon-plus" data-ng-if=!place.latitude></i></md-button></div><md-button data-ng-if="place.typeId !== 4 && place.latitude" aria-label={{messages.editLocation.value}} class="met-flat-button bottom-skimmer" data-ng-click=toggleEditLocation()>{{messages.edit.value}}</md-button><div data-ng-if="place.typeId === 4 && place.imageUrl"><img data-ng-src={{place.imageUrl}}></div><div data-ng-if="place.typeId === 4 && !place.imageUrl" md-theme=mket><div class="image-box empty"><i class="icon icon-truck"></i></div></div></div><div class=place-detail-info-container><div class=content-container><div class=place-job-number><span class=icon-holder><md-icon data-ng-if="place.typeId === 1" class="type-icon icon-clipboard-alert" aria-label="messages.placeType_Unspecified.value messages.icon.value"></md-icon><md-icon data-ng-if="place.typeId === 2" class="type-icon icon-city" aria-label="messages.homeBase.value messages.icon.value"></md-icon><md-icon data-ng-if="place.typeId === 3" class="type-icon icon-home" aria-label="messages.projectJob.value messages.icon.value"></md-icon><md-icon data-ng-if="place.typeId === 4" class="type-icon icon-truck" aria-label="messages.vehicle.value messages.icon.value"></md-icon></span><p><span data-ng-if=place.jobNumber><span data-ng-if="place.typeId === 2">{{messages.jobNumberConversational.value}}</span> <span data-ng-if="place.typeId === 3">{{messages.costCode.value}}</span> <span data-ng-if="place.typeId === 4">{{messages.vehicleNumber.value}}</span><br>{{place.jobNumber}}</span> <span data-ng-if="!place.jobNumber && place.typeId === 2" class="italic light"><br>{{messages.jobNumberConversational.value}}</span> <span data-ng-if="!place.jobNumber && place.typeId === 3" class="italic light"><br>{{messages.costCode.value}}</span> <span data-ng-if="!place.jobNumber && place.typeId === 4" class="italic light"><br>{{messages.vehicleNumber.value}}</span></p></div><span class=bold>{{place.placeName}}</span> <span data-ng-if="place.phoneNumber && place.typeId !== 4">{{place.phoneNumber}}</span> <span data-ng-if="!place.phoneNumber && place.typeId !== 4" class="italic light">{{messages.phoneNumberConversational.value}}</span> <span data-ng-if="place.typeId === 4 && place.vehicleMake">{{place.vehicleMake}}</span> <span data-ng-if="place.typeId === 4 && !place.vehicleMake" class="italic light">{{messages.make.value}}</span> <span data-ng-if="place.typeId === 4 && place.vehicleModel">{{place.vehicleModel}}</span> <span data-ng-if="place.typeId === 4 && !place.vehicleModel" class="italic light">{{messages.model.value}}</span> <span data-ng-if="place.typeId === 4 && place.vehicleYear">{{place.vehicleYear}}</span> <span data-ng-if="place.typeId === 4 && !place.vehicleYear" class="italic light">{{messages.year.value}}</span> <span data-ng-if=place.division>{{place.division.divisionName}}</span> <span data-ng-if=!place.division class="italic light">{{messages.division.value}}</span> <span class=font-13 data-ng-if="place.startDate && place.typeId === 2">{{place.formattedStartDate}} - <span data-ng-if=place.endDate>{{place.formattedEndDate}}</span></span> <span data-ng-if="!place.startDate && place.typeId === 2" class="italic light">{{messages.date.value}} - {{messages.range.value}}</span></div><md-button class="met-flat-button bottom-skimmer" data-ng-click=setEdit(true)>{{messages.edit.value}}</md-button></div></div><div class=place-info-summary><div class=summary-item-container><div class=summary-item><p><i class="icon icon-finger-tap"></i></p><span class=count>{{place.missingToolCount}}</span><p><span>{{messages.markedMissing.value}}</span></p><p><a ng-click="sendToInventory(\'markedMissing\', place)">{{messages.view.value}} <i class="icon icon-chevron-right"></i></a></p></div></div><div class=summary-item-container><div class=summary-item><p><i class="icon icon-hammer-wrench"></i></p><span class=count>{{place.needsServiceToolCount}}</span><p><span>{{messages.needsService.value}}</span></p><p><a ng-click="sendToInventory(\'needsService\', place)">{{messages.view.value}} <i class="icon icon-chevron-right"></i></a></p></div></div><div class=summary-item-container><div class=summary-item><p><i class="icon icon-wifi"></i></p><span class=count>{{place.notSeenInFiveDaysToolCount}}</span><p><span>{{messages.notSeen.value}}</span></p><p><a ng-click="sendToInventory(\'unseen\', place)">{{messages.view.value}} <i class="icon icon-chevron-right"></i></a></p></div></div><div class=summary-item-container ng-if="place.typeId !== 4 && place.enableGeofence && place.geofence.points"><div class=summary-item><p>{{messages.beta.value}}</p><span class=count>{{place.seenOutsideGeofenceCount}}</span><p><span>{{messages.seenOutsideGeofence.value}}</span></p><p><a ng-click="sendToInventory(\'outsideGeofence\', place)">{{messages.view.value}} <i class="icon icon-chevron-right"></i></a></p></div></div><div class=summary-item-container ng-if="place.typeId !== 4 && place.enableGeofence && !place.geofence.points"><div class=summary-item><p><md-button class="md-mini md-fab add-geofence-button" aria-label={{messages.editLocation.value}} ng-click=toggleEditLocation(true)><i class="icon icon-plus"></i></md-button></p><p><a ng-click=toggleEditLocation(true)>{{messages.addGeofence.value}}</a></p></div></div></div><div class=place-info-people><span class="count people-count">{{place.peopleCount}} <span class=assigned-people>{{messages.assignedPeople.value}}</span></span><md-button class="met-flat-button people-edit" ng-click="openPeopleEdit(true, place.placeId)">{{messages.edit.value}}</md-button></div></div><div class=place-data><md-toolbar class=md-toolbar-tools><div class=item-count><span class=count-number>{{place.itemCount}}</span><br><span>{{messages.items.value}}</span></div><div class=place-icon-link><i class="icon icon-briefcase"></i><br><a ng-click="sendToInventory(null, place)">{{messages.manageItems.value}} <i class="icon icon-chevron-right"></i></a></div><div class=place-icon-link><i class="icon icon-tab"></i><br><a ng-click=sendToTransfers(place)>{{messages.transferItems.value}} <i class="icon icon-chevron-right"></i></a></div><div class=place-icon-link><i class="icon icon-file-empty"></i><br><a ng-click=sendToReports(place)>{{messages.createReport.value}} <i class="icon icon-chevron-right"></i></a></div><div><md-button class="met-flat-button secondary bordered" ng-click=exportUserInventoryForPlace(place)>{{messages.downloadInventory.value}}</md-button></div></md-toolbar><div class=place-charts-container><met-tools-by-category-by-place data-place=place ng-if="place.itemCount > 0"></met-tools-by-category-by-place><div class=transfers ng-if="place.itemCount > 0"><div class=content-wrapper><div class=recent-transfers data-ng-if="mostRecentTransfers.length > 0"><span class=number-of-transfers data-ng-cloak><i class="icon icon-tab"></i> {{messages.mostRecentTransfers.value}}</span> <span data-ng-cloak><a ng-click=viewTransferHistory()>{{messages.viewTransferHistoryConversational.value}} <i class="icon icon-chevron-right"></i></a></span></div><div class=transfer-container><div class=transfer-item data-ng-repeat="transfer in mostRecentTransfers" data-ng-if=mostRecentTransfers data-ng-cloak><p class=transfer-data><span><span class=count>{{transfer.count}}</span> <span class=date-text>{{messages.itemsOn.value}} {{transfer.transferredOnLocal | date:dateTimeFormat}}</span></span> <span><a data-ng-click=generate(transfer.id) title download=ToolTransferReport.pdf tabindex="{{($index + 1) + 1}}"><i class="fa fa-file-pdf-o"></i><span class=sr-only>{{messages.generatePdf.value}}</span></a></span></p><div class=transfer-item-names><div><span class=transfer-from>{{transfer.fromLocationName ? transfer.fromLocationName : messages.unspecified.value}}</span> <span class=direction><i class="icon icon-arrow-right"></i></span> <span class=transfer-to>{{transfer.toLocationName ? transfer.toLocationName : messages.unspecified.value}}</span></div></div></div><div class=empty-transfer-item data-ng-if="mostRecentTransfers.length <= 0" data-ng-cloak><i class="icon icon-landscape"></i><p class=subhead>{{messages.noTransferHistory.value}}</p></div></div><div class=create-new-transfer data-ng-if="mostRecentTransfers.length > 0"><span data-ng-cloak><a ng-click=sendToTransfers(place)>{{messages.createATransfer.value}} <i class="icon icon-chevron-right"></i></a></span></div></div></div><div class=empty-place-graph-section ng-if="place.itemCount <= 0 && hasInventoryItems"><i class="icon icon-chart-bars empty-place-graph-icon"></i><div class=empty-place-graph-header>{{messages.gotWhatYouNeed.value}}</div><div class=empty-place-graph-info>{{messages.getItemsAssigned.value}}</div><div class=empty-place-graph-transfer-link><a ng-click=sendToTransfers(place)>{{messages.startATransfer.value}} <i class="icon icon-chevron-right"></i></a></div></div><div class=empty-place-graph-section ng-if="place.itemCount <= 0 && !hasInventoryItems"><i class="icon icon-landscape empty-place-graph-icon"></i><div class=empty-place-graph-header>{{messages.almostThere.value}}</div><div class=empty-place-graph-info>{{messages.placeButNoInvenotryItemsText.value}}</div><div class=empty-place-graph-transfer-link><a href=../inventory/#/add-options>{{messages.addItem.value}} <i class="icon icon-chevron-right"></i></a></div></div></div></div></div><div id=placeDetailEdit_{{place.placeId}} class="place-detail-edit-container slide-animation" data-ng-class="{\'met-hide\' : !isEdit}"><div class=edit-mode-header><span>{{messages.edit.value}}</span> <i data-ng-cloak class="material-icons material-icon-more animate-element" data-ng-click=toggleDeleteMenu()>more_vert</i><div data-ng-cloak class="delete-cta slide-animation" data-ng-class="{\'met-hide\' : !isDeleteMenu}" data-ng-click="showDeleteConfirmDialog(place); closeDeleteMenu()">{{messages.delete.value}}</div></div><div class=place-edit-content><div class=edit-form><div class=form-toolbar><div data-ng-if="place.typeId === 2" class=date-selection><label for=startDateInput_{{place.placeId}}><i id=calendartarget1 class="icon icon-calendar-full"></i></label> <input type=text name=startDateInput id=startDateInput_{{place.placeId}} class=place-date data-ng-model=place.formattedStartDate data-datetimepicker data-datetimepicker-options={{startDatePickerOptions}}></div><div data-ng-if="place.typeId === 2" class=date-selection><label for=endDateInput_{{place.placeId}}><i id=calendartarget2 class="icon icon-calendar-full"></i></label> <input type=text name=endDateInput id=endDateInput_{{place.placeId}} class=place-date data-ng-model=place.formattedEndDate data-datetimepicker data-datetimepicker-options={{endDatePickerOptions}}></div><div class=place-tool-bar-select-item><ui-select data-ng-model=selectedDivision input-id=placeDivision_{{place.placeId}} on-select=onDivisionSelect($item)><ui-select-match placeholder={{messages.division.value}} ng-model=$select.selected>{{$select.selected.divisionName || messages.division.value}}</ui-select-match><ui-select-choices repeat="division in divisions | filter: {\'divisionName\': $select.search} track by division.divisionId" refresh=selectChange($select)><span class=dropdown-options ng-bind-html="\'\'+ division.divisionName | highlight: $select.search"></span></ui-select-choices></ui-select></div></div><div class=edit-place-fields><form name=editPlaceForm><md-input-container><label for=placeName_{{place.placeId}}>{{messages.name.value}}<span class=asterisk>*</span></label> <input id=placeName_{{place.placeId}} data-ng-model=place.placeName name=placeName required aria-required={{messages.required.value}}><div data-ng-messages=editPlaceForm.placeName.$error><div id=editPlaceRequireNameErrorMessage data-ng-message=required>{{messages.required.value}}</div></div></md-input-container><span data-ng-hide=editPlaceForm.$invalid class=sub-input><span class=asterisk>*</span>{{messages.required.value}}</span><span>&nbsp;</span><div class=help-block ng-if=place.errorMessage><i class="icon icon-warning"></i>&nbsp;{{place.errorMessage}}</div><md-input-container data-ng-if="place.typeId === 2"><label for=jobNumber_{{place.placeId}}>{{messages.jobNumberConversational.value}}</label> <input id=jobNumber_{{place.placeId}} data-ng-model=place.jobNumber></md-input-container><md-input-container data-ng-if="place.typeId === 3"><label for=costCode_{{place.placeId}}>{{messages.costCode.value}}</label> <input id=costCode_{{place.placeId}} data-ng-model=place.jobNumber></md-input-container><md-input-container data-ng-if="place.typeId === 2 || place.typeId === 3"><label for=phoneNumber_{{place.placeId}}>{{messages.phoneNumberConversational.value}}</label> <input id=phoneNumber_{{place.placeId}} data-ng-model=place.phoneNumber></md-input-container><md-input-container data-ng-if="place.typeId === 4"><label for=vehicleNumber_{{place.placeId}}>{{messages.vehicleNumber.value}}</label> <input id=vehicleNumber_{{place.placeId}} data-ng-model=place.jobNumber></md-input-container><md-input-container data-ng-if="place.typeId === 4"><label for=vehicleMake_{{place.placeId}}>{{messages.make.value}}</label> <input id=vehicleMake_{{place.placeId}} data-ng-model=place.vehicleMake></md-input-container><md-input-container data-ng-if="place.typeId === 4"><label for=vehicleModel_{{place.placeId}}>{{messages.model.value}}</label> <input id=vehicleModel_{{place.placeId}} data-ng-model=place.vehicleModel></md-input-container><div class=side-by-side><md-input-container class=vehicle-year data-ng-if="place.typeId === 4"><label for=vehicleYear_{{place.placeId}}>{{messages.year.value}}</label> <input id=vehicleYear_{{place.placeId}} data-ng-model=place.vehicleYear></md-input-container><md-input-container class=vehicle-license data-ng-if="place.typeId === 4"><label for=licensePlate_{{place.placeId}}>{{messages.licensePlateConversational.value}}</label> <input id=licensePlate_{{place.placeId}} data-ng-model=place.licensePlate></md-input-container></div></form><div class=action-buttons><md-button class=met-flat-button data-ng-click="setEdit(false, true)">{{ messages.cancel.value }}</md-button><md-button class=met-flat-button data-ng-disabled=editPlaceForm.$invalid data-ng-click=updatePlace(place)>{{ messages.save.value }}</md-button></div></div></div><div class="image-form centered"><upload-place-image image-url=place.imageUrl data-delete-image=deleteImage(place)></upload-place-image></div></div></div><div id=placePeopleEdit_{{place.placeId}} class="place-detail-edit-container slide-animation" data-ng-class="{\'met-hide\' : !isPeopleEdit}"><div class=edit-mode-header><span>{{messages.editPeopleForThisPlace.value}}</span></div><div class=place-edit-content><div class=edit-form><div class=form-toolbar><span class=form-instructions>{{messages.selectNamesToAdd.value}}</span><div class=search-box><i class="icon icon-magnifier"></i> <input id=peopleSearch type=text data-ng-model=searchPersonString placeholder={{messages.searchForAPerson.value}} data-ng-keyup=searchKeyUp($event)> <label for=peopleSearch></label></div></div><div class=edit-place-fields><met-place-people-list data-place=place data-people=people data-people-selection-list=peopleSelectionList data-checkbox-check=handleCheckboxCheck></met-place-people-list><form id=addNewPerson_{{place.placeId}} name=addNewPersonForm><div class=new-person><label for=addNewPersonInput_{{place.placeId}}></label> <input id=addNewPersonInput_{{place.placeId}} type=text data-ng-model=newPersonName data-ng-keyup=newPersonKeyUp($event)> <button data-ng-click=handleNewPersonFormSubmit() ng-disabled=isNewPersonInputEmpty class="met-action-button primary">{{messages.addPersonConversational.value}}</button></div><div data-ng-show=isNewPersonInputEmpty id=empty_{{place.placeId}}>{{messages.required.value}}</div></form></div></div><div class="image-form stretched"><h2 class=selected-people-list-title>{{ messages.assignedPeople.value }}</h2><h3><span class=selected-people-list-count>{{place.personIds.length}}</span> <span class=selected-people-list-sub-title>{{messages.peopleSelected.value}}</span></h3><div class=list-wrapper><ul><li data-ng-repeat="selectedPerson in selectedPeople"><i class="material-icons material-icon-check">check</i> {{selectedPerson.personName}}</li></ul></div><div class=action-buttons><md-button class=met-flat-button data-ng-click="setPeopleEdit(false, false)">{{ messages.cancel.value }}</md-button><md-button class=met-flat-button data-ng-click="updatePlace(place); setPeopleEdit(false, false)">{{ messages.save.value }}</md-button></div></div></div></div><div id=placeLocationEdit_{{place.placeId}} class="place-detail-edit-container slide-animation" data-ng-class="{\'met-hide\' : !isLocationEdit}"><div class=edit-mode-header><span>{{messages.editLocation.value}}</span></div><div class=place-edit-content-vertical><div class=edit-map-address><div class=edit-map><met-place-location class=add-place-map place-model=place data-ng-if=isLocationEdit></met-place-location><div class=action-buttons><md-button class=met-flat-button aria-label={{messages.editLocation.value}} data-ng-click="setEdit(false, false); toggleEditLocation(); cancelLocation()">{{ messages.cancel.value }}</md-button><md-button class=met-flat-button data-ng-disabled="editPlaceForm.$invalid || !place.enableSave" data-ng-click=update(place);>{{ messages.save.value }}</md-button></div></div></div></div></div><div id=placeMigration_{{place.placeId}} class="place-detail-edit-container slide-animation" data-ng-class="{\'met-hide\' : !setType}"><div class=edit-mode-header><span>{{messages.beforeWeCanGetYouDetails.value}}</span></div><div class="place-edit-content set-type"><md-radio-group ng-model=migrationSelectedPlaceType><div class=place-unconverted-content><div class=type-description><i class="icon icon-home"></i><h4>{{messages.homeBase.value}}</h4><p>{{messages.aboutHomeBase_corrected.value}}</p></div><div class=centered-button-container><md-radio-button value=3 aria-label=3></md-radio-button></div></div><div class=place-unconverted-content id=searchCard><div class=type-description><i class="icon icon-city"></i><h4>{{messages.projectJob.value}}</h4><p>{{messages.aboutProjectJob.value}}</p></div><div class=centered-button-container><md-radio-button value=2 aria-label=2></md-radio-button></div></div><div class=place-unconverted-content><div class=type-description><i class="icon icon-truck"></i><h4>{{messages.vehicle.value}}</h4><p>{{messages.aboutVehicle.value}}</p></div><div class=centered-button-container><md-radio-button value=4 aria-label=4></md-radio-button></div></div></md-radio-group><div class=set-type-button-container></div><div class=centered-button-container><button data-ng-disabled="migrationSelectedPlaceType === 0" class="met-action-button primary" data-ng-click=setPlaceType()><span ng-cloak>{{messages.submit.value}}</span></button></div></div></div><div class="action-buttons lone" data-ng-if="place.typeId === 1"><span class=migration-delete-message data-ng-if="place.itemCount > 0">{{messages.deleteWithItems.value.format(place.placeName)}}&nbsp;&nbsp;</span> <span class=migration-delete-message data-ng-if="place.itemCount === 0">{{messages.deleteWithoutItems.value.format(place.placeName)}}&nbsp;&nbsp;</span><md-button class="met-flat-button destructive" data-ng-click=showDeleteConfirmDialog(place)>{{messages.delete.value}}</md-button></div></div></div>');
$templateCache.put('directives/places/metPlacePeopleList.directive.html','<div class=assignPeopleFormContainer><form name=assignPeopleForm ng-show=personsRendered><div id=personEdit_{{person.personId}} class=availablePerson data-ng-repeat="person in peopleSelectionList" ng-init="$last && finished()"><md-checkbox data-ng-model=person.selected aria-label=person.personName data-ng-click=handleCheckboxCheck(person)></md-checkbox><div class=person><span class=personName>{{person.personName}}</span><md-button class=met-flat-button data-ng-click=setEditPerson(person)>{{ messages.edit.value }}</md-button></div></div></form></div>');
$templateCache.put('directives/places/metPlacesList.directive.html','<div data-ng-if=places.length data-ng-repeat="place in places"><met-place data-met-place=place data-met-divisions=divisions data-met-people=people data-met-get-people=getPeople() data-met-collapse-all=collapseAll() data-met-delete-image=deleteImage(place) data-met-delete-place=deletePlace(place) data-met-update-place-counts=updatePlaceCounts() data-met-show-delete-confirm-dialog=showDeleteConfirmDialog(place) data-met-has-inventory-items=hasInventoryItems></met-place></div>');
$templateCache.put('directives/places/metToolsByCategoryByPlace.directive.html','<div class=tbc-place-graph data-ng-cloak><div id=toolsByCategoryByPlaceChartContainer_{{place.placeId}}></div></div>');
$templateCache.put('directives/trades/tradesAdd.html','<div id=onekey-add-object-dialog><div class=modal-spinner data-ng-show=saving><i class="fa fa-spinner fa-spin"></i></div><form novalidate name=addForm data-ng-submit=save(addForm)><div class=modal-header><h3 class=modal-title>{{messages.addDivision.value}}</h3></div><div class=modal-body><div class=form-group data-ng-class="{\'has-error\':!valid}"><label class=control-label for=tradeName>{{messages.divisionTitle.value}} *</label> <input type=text id=tradeName name=tradeName class=form-control required data-ng-model=trade.tradeName data-met-focus-on=loaded maxlength=64 tabindex=10 data-met-enter=save(addForm) ng-change=clearError()><p data-ng-if=duplicate class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ error }}</p></div></div><div class=modal-footer><button type=button class="btn btn-action-black" tabindex=11 data-ng-click=cancel()>{{messages.cancel.value}}</button> <button type=submit class="btn btn-action-blue" tabindex=12>{{messages.save.value}}</button></div></form></div>');
$templateCache.put('custom-modules/add-inventory/templates/add-options.html','<div data-ng-init=vm.initialize()><div class=row data-ng-cloak><div class=header-background id=inventoryAddTitle><label class=inventory-header>{{vm.messages.addInventory.value}}</label></div></div><div class=card-container data-ng-if=!vm.addPlace data-ng-cloak><a ui-sref="search({ fromState: \'search\' })" data-ng-click=vm.setBackgroundLight()><div class=card id=searchCard><img class=card-img-icon src=../../../../../../Content/images/milwaukee-logo_red.png><p class=text-label>{{vm.messages.addMkeTool.value}}</p></div></a> <a background-color ui-sref="existing({fromState: \'existing\'})" data-ng-click=vm.setBackgroundLight()><div class=card id=duplicateCard><i id=search-card-icon class=icon-magnifier></i><p class=text-label>{{vm.messages.createFromExisting.value}}</p></div></a> <a ui-sref="add-new({fromState: \'add-new\'})" data-ng-click=vm.setBackgroundDark()><div class=card id=addCard><i id=search-card-icon class=icon-plus></i><p class=text-label>{{vm.messages.blankEntryForm.value}}</p></div></a> <a ui-sref=upload data-ng-click=vm.setBackgroundDark()><div class=card id=uploadCard><i id=search-card-icon class=icon-upload2></i><p class=text-label>{{vm.messages.uploadFromSpreadsheet.value}}</p></div></a></div></div>');
$templateCache.put('custom-modules/add-inventory/templates/addForm.html','<div class=content data-ng-init=iaCtrl.init()><div class=header-background><label class=inventory-header>{{ iaCtrl.messages.addNewItem.value }}</label></div><div data-ng-show=iaCtrl.displayKit select-from-kit remove-kit-component=iaCtrl.removeKitComponent display-kit=iaCtrl.showHideKit() messages=iaCtrl.messages met-item-count=iaCtrl.itemCount kit-component-manufacturer=iaCtrl.primaryManufacturer id=metSelectFromKit></div><form data-ng-hide=iaCtrl.displayKit id=masterForm name=masterForm class=form-container novalidate><div class="panel ok-panel"><div class=panel-heading>{{ iaCtrl.messages.generalInfo.value }}<span class=onekey-required><span class=red-asterisk>*</span></span></div><div class=panel-body id=generalInfoPanelBody><div forminput id=input-manufacturer class=onekey-form-group3><label>{{iaCtrl.messages.brand.value}} <span class=red-asterisk>*</span></label><met-manufacturer-selector data-ng-model=iaCtrl.addFormModel.manufacturer data-met-disabled=iaCtrl.disableFields data-primary-manufacturer=iaCtrl.primaryManufacturer data-met-manufacturers=iaCtrl.itemFields.manufacturers data-met-on-manufacturer-added=iaCtrl.itemFields.loadManufacturers() data-met-include-placeholder={{iaCtrl.includePlaceholder}} data-met-resolve-to-popup=iaCtrl.resolveToPopup tabindex=1></met-manufacturer-selector></div><div forminput id=input-modelnumber class=onekey-form-group3><label>{{iaCtrl.messages.modelNumber.value}}<span class=red-asterisk>*</span><span class=ui-icon-help></span></label> <input tabindex=2 selected-state type=text name=modelNumber id=modelNumber data-ng-required=true data-ng-model=iaCtrl.addFormModel.modelNumber data-ng-disabled=iaCtrl.disableFields></div><div forminput id=input-description class=onekey-form-group3><label>{{iaCtrl.messages.description.value}}<span class=red-asterisk>*</span></label> <input tabindex=3 selected-state type=text name=description id=description data-ng-required=true data-ng-model=iaCtrl.addFormModel.description></div><div data-ng-show=masterForm.$valid><i class=icon-check></i></div></div></div><div class="panel ok-panel"><div class=panel-heading data-ng-click="iaCtrl.collapse(\'additionalInfoPanel\')" data-ng-class="{ collapsed: iaCtrl.additionalInfoPanel.collapsed }"><span data-ng-if=iaCtrl.additionalInfoPanel.collapsed class=icon-chevron-down></span> <span data-ng-if=!iaCtrl.additionalInfoPanel.collapsed class=icon-chevron-up></span> {{iaCtrl.messages.additionalInfo.value}}</div><div class=panel-body data-ng-hide=iaCtrl.additionalInfoPanel.collapsed><div class=onekey-form-group-5-img><label>{{iaCtrl.messages.productImage.value}}</label> <span data-ng-show=iaCtrl.showThumbForProductImg met-confirm-popover="iaCtrl.removeImage(\'productImage\')" met-confirm-message={{iaCtrl.messages.delete.value}}?></span><div data-ng-show=iaCtrl.showThumbForProductImg id=imageIcon><met-image-thumb data-met-thumb-src=iaCtrl.addFormModel.imageAlternates.smallUrl data-met-detail-src=iaCtrl.addFormModel.imageAlternates.mediumUrl data-met-image-detail-position=right data-met-thumb-class=item-thumbnail-md></met-image-thumb><span met-confirm-popover="iaCtrl.removeImage(\'productImage\')" met-confirm-message={{iaCtrl.messages.delete.value}}?><i class="icon-cross-circle icon-cross-circle-remove-image-icon fa-lg"></i></span></div><div data-ng-hide=iaCtrl.showThumbForProductImg><met-image-uploader met-tab-index=4 data-ng-model=iaCtrl.addFormModel.productImage data-ng-model-list=iaCtrl.detailsQueue data-met-force-image=true data-met-disable-save=false data-met-show-thumb=iaCtrl.showThumbForProductImg data-met-model-alternates=iaCtrl.addFormModel.imageAlternates data-met-upload-url={{iaCtrl.imageUploadUrl}} data-met-on-file-uploaded=iaCtrl.onProductImgUploaded()></met-image-uploader></div></div><div class=onekey-form-group><div class=add-inventory-margin-bottom><div forminput id=input-servicedatepicker><label>{{iaCtrl.messages.serviceDate.value}}</label><div class="inner-addon left-addon"><span class="icon icon-calendar-full"></span> <input type=text id=serviceDate name=serviceDate class="form-control date-control" tabindex=5 data-ng-model=iaCtrl.addFormModel.serviceDate selected-state data-datetimepicker data-datetimepicker-options={{iaCtrl.datePickerOptions}}></div></div></div></div><div forminput id=input-category class=onekey-form-group><label>{{iaCtrl.messages.category.value}}</label><met-category-selector data-ng-model=iaCtrl.addFormModel.category data-met-categories=iaCtrl.itemFields.categories data-met-on-category-added=iaCtrl.itemFields.loadCategories() data-met-include-placeholder={{iaCtrl.includePlaceholder}} data-met-resolve-to-popup=iaCtrl.resolveToPopup></met-category-selector></div><div forminput id=input-trade class=onekey-form-group><label>{{iaCtrl.messages.division.value}}</label><met-trade-selector data-ng-model=iaCtrl.addFormModel.division data-met-trades=iaCtrl.itemFields.trades data-met-resolve-to-popup=iaCtrl.resolveToPopup data-met-on-trade-added=iaCtrl.itemFields.loadTrades() data-met-include-placeholder={{iaCtrl.includePlaceholder}}></met-trade-selector></div></div></div><div class="panel ok-panel"><div class=panel-heading data-ng-click="iaCtrl.collapse(\'purchaseInfoPanel\')" data-ng-class="{ collapsed: iaCtrl.purchaseInfoPanel.collapsed }"><span data-ng-if=iaCtrl.purchaseInfoPanel.collapsed class=icon-chevron-down></span> <span data-ng-if=!iaCtrl.purchaseInfoPanel.collapsed class=icon-chevron-up></span> {{iaCtrl.messages.purchaseInfo.value}}</div><div class=panel-body data-ng-hide=iaCtrl.purchaseInfoPanel.collapsed><div class=onekey-form-group-5-img><label class=label-align-left>{{ iaCtrl.messages.orderInfoImage.value }}</label><div data-ng-show=iaCtrl.showThumbForOrderImg><met-image-thumb data-met-thumb-src=iaCtrl.addFormModel.orderInfoImageAlternates.smallUrl data-met-detail-src=iaCtrl.addFormModel.orderInfoImageAlternates.mediumUrl data-met-image-detail-position=right data-met-thumb-class=item-thumbnail-md></met-image-thumb><span met-confirm-popover="iaCtrl.removeImage(\'orderInfoImageUrl\')" met-confirm-message={{iaCtrl.messages.delete.value}}?><i class="icon-cross-circle icon-cross-circle-remove-image-icon fa-lg"></i></span></div><div data-ng-hide=iaCtrl.showThumbForOrderImg><met-image-uploader met-tab-index=8 data-ng-model=iaCtrl.addFormModel.orderInfoImageUrl data-ng-model-list=iaCtrl.detailsQueue data-met-force-image=true data-met-disable-save=false data-met-show-thumb=iaCtrl.showThumbForOrderImg data-met-model-alternates=iaCtrl.addFormModel.orderInfoImageAlternates data-met-upload-url={{iaCtrl.imageUploadUrl}} data-met-on-file-uploaded=iaCtrl.onOrderInfoImgUploaded()></met-image-uploader></div></div><div class=onekey-form-group-5-img><label>{{iaCtrl.messages.itemizationImage.value}}</label><div data-ng-show=iaCtrl.showThumbForItemizationImg><met-image-thumb data-met-thumb-src=iaCtrl.addFormModel.itemizationImageAlternates.smallUrl data-met-detail-src=iaCtrl.addFormModel.itemizationImageAlternates.mediumUrl data-met-image-detail-position=right data-met-thumb-class=item-thumbnail-md></met-image-thumb><span met-confirm-popover="iaCtrl.removeImage(\'itemizationImageUrl\')" met-confirm-message={{iaCtrl.messages.delete.value}}?><i class="icon-cross-circle icon-cross-circle-remove-image-icon fa-lg"></i></span></div><div data-ng-hide=iaCtrl.showThumbForItemizationImg><met-image-uploader met-tab-index=9 data-ng-model=iaCtrl.addFormModel.itemizationImageUrl data-ng-model-list=iaCtrl.detailsQueue data-met-force-image=true data-met-disable-save=false data-met-show-thumb=iaCtrl.showThumbForItemizationImg data-met-model-alternates=iaCtrl.addFormModel.itemizationImageAlternates data-met-upload-url={{iaCtrl.imageUploadUrl}} data-met-on-file-uploaded=iaCtrl.onItemizationImgUploaded()></met-image-uploader></div></div><div class=onekey-form-group-5><div forminput id=input-purchase-location><label>{{iaCtrl.messages.purchaseLocation.value}}</label> <input tabindex=10 selected-state type=text name=purchaseLocation id=purchaseLocation data-ng-model=iaCtrl.addFormModel.purchaseLocation></div></div><div class=onekey-form-group-5><label>{{iaCtrl.messages.datePurchased.value}}</label> <span class="inner-addon left-addon"><span class="icon icon-calendar-full"></span> <input tabindex=11 selected-state type=text id=datePurchased name=datePurchased class="form-control date-control" data-ng-model=iaCtrl.addFormModel.purchaseDate data-datetimepicker data-datetimepicker-options={{iaCtrl.purchaseDatePickerOptions}}></span></div><div class=onekey-form-group-5><div forminput id=input-purchase-value><label>{{iaCtrl.messages.purchaseValue.value}}</label> <input tabindex=12 selected-state type=text name=purchaseValue id=purchaseValue data-ng-model=iaCtrl.addFormModel.value></div></div></div></div><div class="panel ok-panel" id=quantitycounter><div class="panel-heading collapsed"><span id=quantitySpan class=quantity-text><span>{{iaCtrl.messages.quantity.value}}</span> <a tabindex=13 data-ng-model=iaCtrl.itemCount data-selected-state class=icon-minus id=decrement data-ng-click=iaCtrl.removeItem()></a> <a class=text-center>{{iaCtrl.itemCount}}</a> <a tabindex=14 data-ng-model=iaCtrl.itemCount data-selected-state class="icon icon-plus" id=increment data-ng-click=iaCtrl.increment()></a></span></div></div><div data-ng-repeat="item in iaCtrl.detailsQueue track by $index" class=repeat-item><add-details-pane data-locations=iaCtrl.userLocations data-people=iaCtrl.userPersons data-details-queue=iaCtrl.detailsQueue data-index={{$index}} data-add-item=iaCtrl.addItem data-remove-item=iaCtrl.removeItem($index) input-error=item.errorMessage></add-details-pane></div><div class="panel inventory-form-panel" id=inventoryFormPanelFooter><span class=right-margin-inner id=saveresetgroup name=saveresetgroup><button class="btn btn-primary" id=itemSaveButton name=itemSaveButton data-ng-disabled="masterform.manufacturer.$invalid || masterForm.modelNumber.$invalid || masterForm.description.$invalid" data-ng-click="iaCtrl.removeKitComponent(iaCtrl.selectedKitIndex); iaCtrl.showHideKit(); iaCtrl.saveForm(iaCtrl.addFormModel, iaCtrl.detailsQueue)" disabled>{{iaCtrl.messages.save.value}}</button> <button tabindex=18 class="btn btn-link ng-binding" id=item-reset-button name=itemResetButton data-ng-click=iaCtrl.reset()>{{iaCtrl.messages.cancel.value}}</button></span></div></form></div>');
$templateCache.put('custom-modules/add-inventory/templates/existing.html','<div class=container-fluid id=existing><div class=row><div class=header-background id=inventoryAddTitle><label class=inventory-header>{{ existing.messages.addFromExistingItem.value }}</label></div></div><div class=content-box><div class=row><span class=sub-header>{{ existing.messages.addExistingSearchInstructionsRedux.value}}</span></div><form novalidate name=existingSearchForm data-ng-submit=existing.search()><div class=form-group><div class=search><span data-ng-hide="existingSearchForm.existingSearch.$viewValue.length > 20" class="icon icon-magnifier"></span> <input data-met-enter=existing.search() type=text id=existingSearch name=existingSearch data-ng-model=existing.searchTerm><div class="btn btn-primary" data-ng-click=existing.search()>{{ existing.messages.search.value }}</div></div></div></form><div data-ng-cloak data-ng-show=existing.loading class=results-grid-message><i class="fa fa-spinner fa-spin"></i> {{ existing.messages.searching.value }}</div><div class=status-message data-ng-show="!loading && noInventory">{{ existing.messages.noMatches.value }}.</div><div data-ng-show="existing.showResults && !existing.noInventory"><div class=results-header>{{ existing.itemCount }} {{ existing.messages.resultsFor.value}} "{{ existing.searchTerm }}"</div><table class="table table_AddMilwaukeeSearch"><thead><tr><th class=small>{{existing.messages.inventoryToolNumber.value}}</th><th class=small>{{existing.messages.modelNumberShort.value}}</th><th class=small>{{existing.messages.modelDescription.value}}</th><th class=small>{{existing.messages.manufacturer.value}}</th><th class=small>{{existing.messages.category.value}}</th><th class=small>{{existing.messages.division.value}}</th><th></th></tr></thead><tbody><tr data-ng-repeat="item in existing.items"><td>{{ item.toolNumber }}</td><td>{{ item.model }}</td><td>{{ item.description }}</td><td>{{ item.manufacturer }}</td><td>{{ item.category }}</td><td>{{ item.trade }}</td><td><div data-ng-click=existing.selectItem(item) class=onekey-button-lightblue tabindex=4>{{ existing.messages.add.value }}</div></td></tr></tbody></table></div></div></div>');
$templateCache.put('custom-modules/add-inventory/templates/formPane.html','');
$templateCache.put('custom-modules/add-inventory/templates/itemDetailsPane.html','<div class="panel ok-panel" style="margin-top: 0; padding-top: 0;"><div class=panel-heading><strong>{{count}}</strong>. {{messages.itemDetails.value}} <span data-ng-show=canRemove() class=icon-cross data-ng-click=removeItem(index)></span></div><div class=panel-body><div forminput id=inputserialnumber class=onekey-form-group><label>{{messages.serialNumber.value}}</label> <input data-selected-state tabindex={{tabindices[0]}} type=text name=serialNumber id=serialNumber data-ng-model=detailsQueue[index].serialNumber> <span data-ng-model=detailsQueue[index].errorMessage data-ng-if=inputError class="control-label bottomless addItemErrorMessage">{{ detailsQueue[index].errorMessage }}</span> <span data-ng-if=serialNumberError class="control-label bottomless addItemErrorMessage">{{ messages.serialNumberRequired.value }}</span></div><div forminput id=input-tool-number class=onekey-form-group><label>{{messages.toolNumber.value}}</label> <input tabindex={{tabindices[0]}} data-selected-state type=text name=toolNumber id=toolNumber data-ng-model=detailsQueue[index].toolNumber></div><div forminput id=input-location class=onekey-form-group><label>{{messages.place.value}}</label><met-location-selector name=locationName data-ng-model=detailsQueue[index].location data-met-locations=itemFields.locations data-met-tabindex={{tabindices[0]}} data-met-on-location-added=itemFields.loadLocations() met-resolve-to-popup=useModal data-met-include-placeholder={{includePlaceholder}}></met-location-selector></div><div forminput id=input-person class=onekey-form-group><label>{{messages.addPerson.value}}</label><met-person-selector name=personName data-ng-model=detailsQueue[index].person data-met-people=itemFields.people data-met-resolve-to-popup=true data-met-tabindex={{tabindices[0]}} data-met-on-person-added=itemFields.loadPeople() data-met-include-placeholder={{includePlaceholder}}></met-person-selector></div></div></div>');
$templateCache.put('custom-modules/add-inventory/templates/milwaukee-search.html','<div class=wrapper background-color><div data-ng-init=searchCtrl.initialize()><div class=header-background id=inventoryAddTitle><label class=inventory-header>{{ searchCtrl.messages.addMkeTool.value }}</label></div></div><div class=content-box><div class=row><div class=col-md-6>{{ searchCtrl.messages.addMkeSearchInstructions.value }}<span><a blank-target-link url=searchCtrl.url style=color:#076AE6;>&nbsp;{{searchCtrl.displayUrl}}.</a></span></div></div><div class=affixed-header-wrapper><div class=affixed-header-searchbar id=existingSearchBar><div class=form-group><div class=search id=mkeSearchBox><span class="icon icon-magnifier"></span> <input type=text id=existingSearch name=existingSearch data-ng-model=searchCtrl.searchTerm data-ng-model-options="{ debounce: 1000 }" data-ng-change=searchCtrl.trySearch() data-met-focus-on=searchCtrl.searchModel.show><div class="btn btn-primary" data-ng-click=searchCtrl.trySearch()>{{ searchCtrl.messages.search.value }}</div></div></div><div data-ng-cloak data-ng-show=searchCtrl.loading class=results-grid-message><i class="fa fa-spinner fa-spin"></i> {{ searchCtrl.messages.searching.value }}</div></div><div data-ng-hide="!searchCtrl.showResults || searchCtrl.displayKit" data-ng-show="searchCtrl.showNoResults || !searchCtrl.displayKit"><div class=results-header>{{ searchCtrl.itemCount }} {{ searchCtrl.messages.resultsFor.value }} "{{ searchCtrl.searchTerm }}"</div><table class="table table_AddMilwaukeeSearch" id=mkeSearchResultsHeader><thead><tr><th class="no-sort medium" id=thSort></th><th class="no-sort medium" id=thSort>{{ searchCtrl.messages.modelNumber.value }}</th><th class=no-sort id=thSort>{{searchCtrl.messages.itemDescription.value }}</th><th class=small></th></tr></thead><tbody><tr data-ng-repeat="result in searchCtrl.searchResults | limitTo:100"><td><met-image-thumb data-met-thumb-src=result.imageAlternates.smallUrl data-met-detail-src=result.imageAlternates.mediumUrl data-met-image-detail-position=right></met-image-thumb></td><td>{{ result.modelNumber }}</td><td>{{ result.itemDescription }}<p data-ng-if=result.isTick class=warning-message ng-bind-html="searchCtrl.messages.tickPairing.value | rawHtml"></p></td><td ng-switch=result.isTick><div data-ng-click=searchCtrl.selectItem(result) class=onekey-button-lightblue tabindex=4 ng-switch-when=false>{{searchCtrl.messages.addBtn.value }}</div></td></tr></tbody></table></div></div></div></div>');
$templateCache.put('custom-modules/add-inventory/templates/selectFromKit.html','<div class=container-fluid><table class="table table_AddMilwaukeeSearch" id=mkeSearchResultsHeader><thead><tr><th class="no-sort medium" id=thSort></th><th class="no-sort medium" id=thSort>{{messages.modelNumber.value }}</th><th class=no-sort id=thSort>{{messages.itemDescription.value }}</th><th class=small></th></tr></thead><tbody><tr data-ng-repeat="result in addFormModel.kit track by $index"><td><met-image-thumb data-met-thumb-src=result.imageAlternates.smallUrl data-met-detail-src=result.imageAlternates.mediumUrl data-met-image-detail-position=right></met-image-thumb></td><td>{{ result.modelNumber }}</td><td>{{ result.itemDescription }}<p ng-if=result.isTick class=warning-message>{{ messages.tickPairing.value }}</p></td><td><div data-ng-click="select(result, $index)" class=onekey-button-lightblue tabindex=4>{{messages.addBtn.value }}</div></td></tr></tbody></table></div>');
$templateCache.put('custom-modules/add-inventory/templates/successSummary.html','<div class=row><div class=col-md-push-4><div class=success-panel id=addItemSuccessPanel><span-bold id=successHeading><i class=icon-check id=addSuccessCheck></i>{{messages.addItemSuccessMessage.value}} {{summaries.length}} {{messages.itemsAddedSuccessfully.value}}</span-bold><p id=summaryRow1><b>{{summaries[0].data.manufacturerName}}</b></p><p id=summaryRow2>{{summaries[0].data.modelNumber}}</p><p id=summaryRow3>{{summaries[0].data.description}}</p></div></div></div>');
$templateCache.put('custom-modules/add-inventory/templates/upload.html','<div data-ng-controller=UploadCtrl data-ng-init=init()><div class="alert alert-danger validation-summary-errors" ng-hide="uploading || !uploadErrors"><ul class=excel-error-row ng-repeat="error in uploadErrors"><li>{{ error }}</li></ul><ul class=excel-error-row><li ng-repeat="errorRow in uploadRowErrors | orderBy: \'rowNumber\'">{{ messages.excelRow.value }}: {{ errorRow.rowNumber }}<ul class=excel-row-errors><li ng-repeat="error in errorRow.errors">{{ error }}</li></ul></li></ul></div><div class=header-background><label class=inventory-header>{{messages.addFromSpreadsheet.value}}</label></div><div class=content-box><div class=row><div class=col-md-6><div class="box excel-page-box"><p class="excel-instructions line-one">{{messages.excelDownloadInstructions1.value}}</p><p class="excel-instructions line-two">{{messages.excelDownloadInstructions2.value}}</p><a class="btn excel-upload-azura" ng-href={{path}}><div class=icon-download2 id=download-icon></div><div id=download-text>{{messages.downloadTemplate.value}}</div></a></div></div><div class=col-md-6><div class="box excel-page-box"><p class="excel-instructions line-one">{{messages.excelUploadInstructions1.value}}</p><p class="excel-instructions line-two">{{messages.excelUploadInstructions2.value}}.</p><div class=col-md-6><a ngf-select=fileChanged($files) accept=* class="btn excel-upload-azura" href={{templateUpload}}><div class=icon-upload2 id=download-icon></div><div id=download-text>{{ messages.uploadTemplate.value }}</div></a></div><div class=clearfix><span id=uploadFileNameText>{{ uploadFile.name }}</span></div><div id=saveCancelUploadButtons class=btn-group><button class="btn btn-link" tabindex=1 data-ng-click=clearForm()>{{messages.reset.value}}</button> <button class="btn btn-primary" tabindex=2 data-ng-click=fileUpload($event) data-ng-disabled=uploading>{{messages.save.value}}</button> <span class="fa inline-spinner fa-spinner fa-spin" data-ng-show=uploading></span></div></div></div></div></div></div>');
$templateCache.put('custom-modules/add-place/templates/add-place-options.html','<div class=place-darker-background data-ng-init=vm.initialize()><div class=row data-ng-cloak><div class=header-background id=inventoryAddTitle><label class=inventory-header><i ui-sref=places class="icon-arrow-left back-arrow"></i> {{vm.messages.addPlace.value}}</label></div></div><div class=add-card-container data-ng-cloak><div class=place-add-card id=searchCard><i class="icon icon-city"></i><h4>{{vm.messages.jobProject.value}}</h4><p>{{vm.messages.addThisPlaceType.value}}</p><div class=inventory-buttons><a class="met-action-button primary" data-ng-click=vm.setBackgroundLight() ui-sref="add-place({ placeType: \'projectJob\' })">{{vm.messages.add.value}}</a></div></div><div class=place-add-card><i class="icon icon-home"></i><h4>{{vm.messages.homeBase.value}}</h4><p>{{vm.messages.addThisPlaceType.value}}</p><div class=inventory-buttons><a class="met-action-button primary" data-ng-click=vm.setBackgroundLight() ui-sref="add-place({ placeType: \'homeBase\' })">{{vm.messages.add.value}}</a></div></div><div class=place-add-card><i class="icon icon-truck"></i><h4>{{vm.messages.vehicle.value}}</h4><p>{{vm.messages.addThisPlaceType.value}}</p><div class=inventory-buttons><a class="met-action-button primary" data-ng-click=vm.setBackgroundLight() ui-sref="add-place({ placeType: \'vehicle\' })">{{vm.messages.add.value}}</a></div></div></div></div>');
$templateCache.put('custom-modules/add-place/templates/addPlaceDetails.html','<div class=add-detail-section><div class=form-toolbar><div data-ng-if="addPlaceModel.typeId === 2" class=date-selection><label for=startDateInput><i id=calendartarget1 class="icon icon-calendar-full"></i></label> <input type=text name=startDateInput id=startDateInput class=place-date data-ng-model=addPlaceModel.startDateTime data-datetimepicker data-datetimepicker-options={{startDatePickerOptions}}></div><div data-ng-if="addPlaceModel.typeId === 2" class=date-selection><label for=endDateInput><i id=calendartarget2 class="icon icon-calendar-full"></i></label> <input type=text name=endDateInput id=endDateInput class=place-date data-ng-model=addPlaceModel.endDateTime data-datetimepicker data-datetimepicker-options={{endDatePickerOptions}}></div><div class=place-tool-bar-select-item><ui-select data-ng-model=addPlaceModel.divisionId uis-open-close=onDropDownOpenClose(isOpen) search-enabled=true input-id=uisDivisions on-select=onDivisionSelect($item)><ui-select-match placeholder={{messages.searchOrAdd.value}} ng-model=$select.selected>{{$select.selected.divisionId !== -1 ? $select.selected.divisionName : messages.division.value}}</ui-select-match><ui-select-choices group-by=firstLetterDivisionGroupFn group-filter=orderFilterFn position=down repeat="division.divisionId as division in (divisions | filter: {\'divisionName\': $select.search}) track by division.divisionId"><span class=dropdown-options ng-bind-html="\'\'+ division.divisionName | highlight: $select.search"></span></ui-select-choices><ui-select-no-choice><span class=add-option>{{messages.noResultsFound.value}}</span></ui-select-no-choice></ui-select><div class=add-division-button><button id=addNewDivision ng-click=triggerAddNewDivision() type=button><i class="icon icon-plus"></i></button></div></div></div><div id=input-number class=add-details-text><md-input-container data-ng-if="addPlaceModel.typeId === 2"><label>{{messages.jobProjectNumber.value}}</label> <input md-maxlength=50 data-ng-model=addPlaceModel.jobNumber maxlength=50 aria-label={{messages.jobProjectNumber.value}}></md-input-container><md-input-container data-ng-if="addPlaceModel.typeId === 3"><label>{{messages.homeBaseNumber.value}}</label> <input md-maxlength=50 data-ng-model=addPlaceModel.jobNumber maxlength=50 aria-label={{messages.homeBaseNumber.value}}></md-input-container><md-input-container data-ng-if="addPlaceModel.typeId === 4"><label>{{messages.vehicleNumber.value}}</label> <input md-maxlength=50 data-ng-model=addPlaceModel.jobNumber maxlength=50 aria-label={{messages.vehicleNumber.value}}></md-input-container></div><div id=input-phone-number class=add-details-text data-ng-if="addPlaceModel.typeId !== 4"><md-input-container><label>{{messages.phoneNumber.value}}</label> <input md-maxlength=50 data-ng-model=addPlaceModel.phoneNumber maxlength=50></md-input-container></div><div id=input-vehilce-make class=add-details-text data-ng-if="addPlaceModel.typeId === 4"><md-input-container><label>{{messages.make.value}}</label> <input md-maxlength=50 data-ng-model=addPlaceModel.vehicleMake maxlength=50></md-input-container></div><div id=input-vehilce-model class=add-details-text data-ng-if="addPlaceModel.typeId === 4"><md-input-container><label>{{messages.model.value}}</label> <input md-maxlength=50 data-ng-model=addPlaceModel.vehicleModel maxlength=50></md-input-container></div><div class=vehicle-detail-line><div id=input-vehilce-year class=add-details-year data-ng-if="addPlaceModel.typeId === 4"><md-input-container><label>{{messages.year.value}}</label> <input md-maxlength=4 data-ng-model=addPlaceModel.vehicleYear maxlength=4 ng-keypress=isNumberKey($event)></md-input-container></div><div id=input-vehilce-license class=add-details-license data-ng-if="addPlaceModel.typeId === 4"><md-input-container><label>{{messages.licensePlate.value}}</label> <input md-maxlength=50 data-ng-model=addPlaceModel.licensePlate maxlength=50></md-input-container></div></div></div><div class=image-section><upload-place-image image-url=addPlaceModel.imageUrl delete-image=deleteImage(addPlaceModel)></upload-place-image></div>');
$templateCache.put('custom-modules/add-place/templates/addPlaceForm.html','<div class=content data-ng-init=paCtrl.init()><div class=header-background><label class=inventory-header data-ng-if="paCtrl.addPlaceModel.typeId === 2"><i ui-sref=add-place-options class="icon-arrow-left back-arrow"></i> {{ paCtrl.messages.addProjectJob.value }}</label> <label class=inventory-header data-ng-if="paCtrl.addPlaceModel.typeId === 3"><i ui-sref=add-place-options class="icon-arrow-left back-arrow"></i> {{ paCtrl.messages.addHomeBase.value }}</label> <label class=inventory-header data-ng-if="paCtrl.addPlaceModel.typeId === 4"><i ui-sref=add-place-options class="icon-arrow-left back-arrow"></i> {{ paCtrl.messages.addVehicle.value }}</label></div><div name=masterForm class=form-container><form id=masterForm><div class="panel ok-panel add-place-panel panel-name"><div class=panel-heading>{{ paCtrl.messages.nameYourPlace.value }}</div><div class=panel-body id=generalInfoPanelBody><div id=input-description class=add-place-name><md-input-container data-ng-if="paCtrl.addPlaceModel.typeId === 2"><label for=placeName>{{paCtrl.messages.jobProjectName.value}}<span class=asterisk>&#42;</span></label> <input md-maxlength=50 id=placeName name=placeName data-ng-model=paCtrl.addPlaceModel.placeName maxlength=50 aria-label={{paCtrl.messages.jobProjectName.value}}></md-input-container><md-input-container data-ng-if="paCtrl.addPlaceModel.typeId === 3"><label>{{paCtrl.messages.homeBaseName.value}}</label> <input md-maxlength=50 data-ng-model=paCtrl.addPlaceModel.placeName maxlength=50 aria-label={{paCtrl.messages.homeBaseName.value}}></md-input-container><md-input-container data-ng-if="paCtrl.addPlaceModel.typeId === 4"><label>{{paCtrl.messages.vehicleName.value}}</label> <input md-maxlength=50 data-ng-model=paCtrl.addPlaceModel.placeName maxlength=50 aria-label={{paCtrl.messages.vehicleName.value}}></md-input-container><span data-ng-hide=masterForm.$invalid class=sub-input><span class=asterisk>&#42;</span>{{paCtrl.messages.required.value}}</span><span>&nbsp;</span></div></div></div><div class="panel ok-panel add-place-panel"><div class="panel-heading detail-heading" data-ng-click="paCtrl.collapse(\'addDetail\')" data-ng-class="{ collapsed: paCtrl.addDetail.collapsed }">{{paCtrl.messages.addDetail.value}} <span data-ng-if=paCtrl.addDetail.collapsed class="icon-chevron-down chevron-right"></span> <span data-ng-if=!paCtrl.addDetail.collapsed class="icon-chevron-up chevron-right"></span></div><div class=panel-body data-ng-hide=paCtrl.addDetail.collapsed><add-place-details class=details-section divisions=paCtrl.itemFields.trades data-met-delete-image=deleteImage(paCtrl.addPlaceModel) add-place-model=paCtrl.addPlaceModel></add-place-details></div></div><div class="panel ok-panel add-place-panel"><div class="panel-heading detail-heading" data-ng-click="paCtrl.collapse(\'addPeople\')" data-ng-class="{ collapsed: paCtrl.addPeople.collapsed }">{{paCtrl.messages.addPeople.value}} <span data-ng-if=paCtrl.addPeople.collapsed class="icon-chevron-down chevron-right"></span> <span data-ng-if=!paCtrl.addPeople.collapsed class="icon-chevron-up chevron-right"></span></div><div class="panel-body add-people-panel" data-ng-hide=paCtrl.addPeople.collapsed><div id=addPlaceAssignPeople class=place-detail-edit-container><place-people all-people=paCtrl.allPeople place-model=paCtrl.addPlaceModel is-add=paCtrl.addMode></place-people></div></div></div><div class="panel ok-panel add-place-panel" data-ng-if="paCtrl.addPlaceModel.typeId !== 4"><div class="panel-heading detail-heading" data-ng-click="paCtrl.collapse(\'setLocation\')" data-ng-class="{ collapsed: paCtrl.setLocation.collapsed }">{{paCtrl.messages.setLocationAndGeofence.value}} <span data-ng-if=paCtrl.setLocation.collapsed class="icon-chevron-down chevron-right"></span> <span data-ng-if=!paCtrl.setLocation.collapsed class="icon-chevron-up chevron-right"></span></div><div class=panel-body data-ng-hide=paCtrl.setLocation.collapsed><met-place-location data-ng-if=!paCtrl.setLocation.collapsed class=add-place-map place-model=paCtrl.addPlaceModel></met-place-location></div></div><div class="panel footer-panel" id=inventoryFormPanelFooter><span class=right-margin-inner id=saveresetgroup name=saveresetgroup><button class="btn btn-primary" id=itemSaveButton name=itemSaveButton data-ng-disabled data-ng-click=paCtrl.showSubmitConfirm($event) type=button>{{paCtrl.messages.submit.value}}</button> <button tabindex=18 class="btn btn-link ng-binding" id=item-reset-button name=itemResetButton data-ng-click=paCtrl.showConfirm($event) type=button>{{paCtrl.messages.cancel.value}}</button></span></div></form></div></div>');
$templateCache.put('custom-modules/add-place/templates/placePeople.html','<div class=place-edit-content><div class=edit-form><div class=form-toolbar><span class=form-instructions>{{messages.selectNamesToAdd.value}}</span><div class=search-box><i class="icon icon-magnifier"></i> <input id=peopleSearch type=text data-ng-model=searchPersonString placeholder={{messages.searchForAPerson.value}} data-ng-keyup=searchKeyUp($event)> <label for=peopleSearch></label></div></div><div class=edit-place-fields><div class=assignPeopleFormContainer><form name=assignPeopleForm ng-show=personsRendered><div id=personEdit_{{person.personId}} class=availablePerson data-ng-repeat="person in peopleSelectionList" ng-init="$last && finished()"><md-checkbox data-ng-model=person.selected aria-label=person.personName data-ng-click=handleCheckboxCheck(person)></md-checkbox><div class=person><span class=personName>{{person.personName}}</span><md-button class=met-flat-button data-ng-click=setEditPerson(person)>{{ messages.edit.value }}</md-button></div></div></form></div><form id=addNewPerson_{{placeModel.placeId}} name=addNewPersonForm><div class=new-person><label for=addNewPersonInput_{{placeModel.placeId}}></label> <input id=addNewPersonInput_{{placeModel.placeId}} type=text data-ng-model=newPersonName data-ng-keyup=newPersonKeyUp($event)> <button data-ng-click=handleNewPersonFormSubmit(placeModel) ng-disabled=isNewPersonInputEmpty class="met-action-button primary">{{messages.addPersonConversational.value}}</button></div><div data-ng-show=isNewPersonInputEmpty id=empty_{{placeModel.placeId}}>{{messages.required.value}}</div></form></div></div><div class="image-form stretched"><div><h2 class=selected-people-list-title>{{ messages.assignedPeople.value }}</h2><h3><span class=selected-people-list-count>{{placeModel.peopleCount}}</span> <span class=selected-people-list-sub-title>{{messages.peopleSelected.value}}</span></h3><div class=list-wrapper><ul><li data-ng-repeat="selectedPerson in selectedPeople"><i class="material-icons material-icon-check">check</i> {{selectedPerson.personName}}</li></ul></div></div><div class=action-buttons data-ng-if=!isAdd><md-button class=met-flat-button data-ng-click="setPeopleEdit(false, true)">{{ messages.cancel.value }}</md-button><md-button class=met-flat-button data-ng-click="updatePlace(place); setPeopleEdit(false, false)">{{ messages.save.value }}</md-button></div></div></div>');
$templateCache.put('custom-modules/add-place/templates/submitConfirmDialog.html','<md-dialog aria-label=messages.submissionConfirmation.value><form ng-cloak><md-toolbar class=add-place-confirm-box-toolbar><div class><h3>{{messages.submissionConfirmation.value}}</h3><div class=confirm-sub-header>{{messages.pleaseConfirmSubmission.value}}</div><span flex></span></div></md-toolbar><md-dialog-content><div class=md-dialog-content><div class=add-place-confirm-container><div class=add-place-confirm-image data-ng-if=addPlaceModel.imageUrl><img class=place-image-thumbnail data-ng-src={{addPlaceModel.imageUrl}} alt></div><div class=add-place-confirm-details><div class=add-place-confirm-type-header><div class=add-place-confirm-detail-header>{{messages.placeType.value}}</div><div class=add-place-confirm-footnote>{{messages.nonEditableAfterSubmission.value}}</div></div><div ng-if="addPlaceModel.typeId === 2"><i class=icon-city></i> {{messages.placeTypeProjectJob.value}}</div><div ng-if="addPlaceModel.typeId === 3"><i class=icon-home></i> {{messages.placeTypeHomeBase.value}}</div><div ng-if="addPlaceModel.typeId === 4"><i class=icon-truck></i> {{messages.placeTypeVehicle.value}}</div><div class="add-place-confirm-detail-header add-place-confirm-header-secondary">{{messages.details.value}}</div><div class=add-place-confirm-detail-info data-ng-if="addPlaceModel.typeId === 2"><div class=add-confirm-start-date data-ng-if=addPlaceModel.startDateTime>{{addPlaceModel.startDateTime}}</div><div class="add-place-confirm-place-holder add-confirm-start-date" data-ng-if=!addPlaceModel.startDateTime>{{messages.startDate.value}}</div>-<div class=add-confirm-end-date data-ng-if=addPlaceModel.endDateTime>{{addPlaceModel.endDateTime}}</div><div class="add-place-confirm-place-holder add-confirm-end-date" data-ng-if=!addPlaceModel.endDateTime>{{messages.endDate.value}}</div></div><div class=add-place-confirm-detail-info><div data-ng-if="divisionName && divisionId > -1">{{divisionName}}</div><div class=add-place-confirm-place-holder data-ng-if="!divisionName || divisionId === -1">{{messages.division.value}}</div></div><div class=add-place-confirm-detail-info>{{addPlaceModel.placeName}}</div><div class=add-place-confirm-detail-info><div data-ng-if=addPlaceModel.jobNumber>{{addPlaceModel.jobNumber}}</div><div class=add-place-confirm-place-holder data-ng-if="!addPlaceModel.jobNumber && addPlaceModel.typeId === 2">{{messages.jobProjectNumber.value}}</div><div class=add-place-confirm-place-holder data-ng-if="!addPlaceModel.jobNumber && addPlaceModel.typeId === 3">{{messages.homeBaseNumber.value}}</div><div class=add-place-confirm-place-holder data-ng-if="!addPlaceModel.jobNumber && addPlaceModel.typeId === 4">{{messages.vehicleNumber.value}}</div></div><div class=add-place-confirm-detail-info data-ng-if="addPlaceModel.typeId !== 4"><div data-ng-if=addPlaceModel.phoneNumber>{{addPlaceModel.phoneNumber}}</div><div class=add-place-confirm-place-holder data-ng-if=!addPlaceModel.phoneNumber>{{messages.phoneNumber.value}}</div></div><div class=add-place-confirm-detail-info data-ng-if="addPlaceModel.typeId === 4"><div data-ng-if=addPlaceModel.vehicleMake>{{addPlaceModel.vehicleMake}}</div><div class=add-place-confirm-place-holder data-ng-if=!addPlaceModel.vehicleMake>{{messages.make.value}}</div></div><div class=add-place-confirm-detail-info data-ng-if="addPlaceModel.typeId === 4"><div data-ng-if=addPlaceModel.vehicleModel>{{addPlaceModel.vehicleModel}}</div><div class=add-place-confirm-place-holder data-ng-if=!addPlaceModel.vehicleModel>{{messages.model.value}}</div></div><div class=add-place-confirm-detail-info data-ng-if="addPlaceModel.typeId === 4"><div data-ng-if=addPlaceModel.vehicleYear>{{addPlaceModel.vehicleYear}}</div><div class=add-place-confirm-place-holder data-ng-if=!addPlaceModel.vehicleYear>{{messages.year.value}}</div></div><div class=add-place-confirm-detail-info data-ng-if="addPlaceModel.typeId === 4"><div data-ng-if=addPlaceModel.licensePlate>{{addPlaceModel.licensePlate}}</div><div class=add-place-confirm-place-holder data-ng-if=!addPlaceModel.licensePlate>{{messages.licensePlate.value}}</div></div><div class="add-place-confirm-detail-header add-place-confirm-header-secondary">{{messages.addPeople.value}}</div><div><div data-ng-if="addPlaceModel.peopleCount > 0" data-ng-repeat="person in selectedPeople">{{person.personName}}</div></div><div data-ng-if="addPlaceModel.typeId !== 4"><div class="add-place-confirm-detail-header add-place-confirm-header-secondary">{{messages.setLocation.value}}</div><div class=add-place-confirm-detail-info><div data-ng-if=addPlaceModel.addressLine>{{addPlaceModel.addressLine}}</div><div class=add-place-confirm-place-holder data-ng-if=!addPlaceModel.addressLine>{{messages.addressLine.value}}</div></div><div class=add-place-confirm-detail-info><div data-ng-if=addPlaceModel.cityStateZip>{{addPlaceModel.cityStateZip}}</div><div class=add-place-confirm-place-holder data-ng-if=!addPlaceModel.cityStateZip>{{messages.cityStateZip.value}}</div></div><div class=add-place-confirm-detail-info><div data-ng-if=addPlaceModel.geofence.points><i class=icon-check></i> {{messages.geofenceSet.value}}</div></div></div></div></div></div></md-dialog-content><div class=md-actions layout=row layout-align="end center"><span flex></span><md-button class=met-flat-button ng-click="answer(\'cancel\')">{{messages.back.value}}</md-button><md-button class="btn btn-primary" ng-click="answer(\'submit\')">{{messages.continueSubmit.value}}</md-button></div></form></md-dialog>');
$templateCache.put('custom-modules/add-place/templates/uploadPlaceImage.html','<div class=place-image><div data-ng-show=!imageUrl class=drop-and-caption><div class=drop-box ngf-drop ngf-select ng-model=files ngf-drag-over-class=dragover ngf-multiple=true ngf-allow-dir=true accept=image/*,application/pdf ngf-pattern="\'image/*,application/pdf\'"><div class=drop-content><div><em class="icon icon-cloud-download upload-icon"></em></div><div>{{messages.dragAndDropUpload.value}}</div><div ngf-no-file-drop>{{messages.dragAndDropNotSupported.value}}</div><div class=drag-drop-browse>{{messages.browse.value}}</div></div></div><div data-ng-if=!imageUrl><span class=caption-text>{{messages.imagesWillDisplayOnYourPlacesList.value}}</span></div></div><img data-ng-if=imageUrl class=place-image-thumbnail data-ng-src={{imageUrl}} alt><div class=action-buttons data-ng-show=imageUrl><md-button class=met-flat-button ngf-drop ngf-select ng-model=files ngf-drag-over-class=dragover ngf-multiple=true ngf-allow-dir=true accept=image/*,application/pdf ngf-pattern="\'image/*,application/pdf\'" type=button>{{ messages.replace.value }}</md-button><md-button class=met-flat-button data-ng-click=deleteImage() type=button>{{ messages.delete.value }}</md-button></div></div>');
$templateCache.put('custom-modules/core/partials/_add-category-modal.html','<div class="modal-content add-options-modal-modal-shell" ng-init=vm.categoryInit()><div class=modal-header><h3 class=modal-heading>{{vm.categoryMessages.add.value}} {{vm.categoryMessages.addCategory.value}}</h3><i data-ng-if=vm.saving class="modal-spinner fa fa-spinner fa-spin"></i><form novalidate name=vm.addForm><div class=modal-body><div class=form-group><input type=text id=categoryName name=categoryName class=form-control required data-ng-model=vm.category.categoryName data-met-focus-on=loaded maxlength=64 tabindex=1 data-met-enter="vm.save(\'category\', vm.category)" ng-change=vm.clearError()><p data-ng-if=vm.error class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ vm.error }}</p></div><div forminput id=onekey-add-object-dialog_parent-category-selector class=form-group><label class="control-label modal-heading">{{vm.messages.parentCategoryOptional.value}}</label><met-category-selector name=categoryId data-ng-model=vm.category.parentCategory data-met-categories=vm.categories data-met-include-placeholder=true data-met-exclude-add-option=true></met-category-selector><span data-ng-show="vm.addForm.$valid && !vm.error" class=icon-check></span></div></div></form><div class=modal-footer><button type=button class="btn btn-link" tabindex=2 data-ng-click="vm.cancel(\'cancel\')">{{vm.categoryMessages.cancel.value}}</button> <button type=submit data-ng-disabled="vm.category.categoryName === undefined" class="btn btn-action-blue" tabindex=3 data-ng-click="vm.save(\'category\', vm.category)">{{vm.categoryMessages.save.value}}</button></div></div></div>');
$templateCache.put('custom-modules/core/partials/_add-location-modal.html','<div class="modal-content add-options-modal-modal-shell" data-ng-init=modalInit()><div class=modal-spinner data-ng-show=saving><i class="fa fa-spinner fa-spin"></i></div><form novalidate name=addLocationForm><div class=modal-header><h3 class=modal-title>{{modalMessages.add.value}} {{modalMessages.place.value}}</h3></div><div class=modal-body><div class=form-group><input type=text id=addLocationForm name=location class=form-control required data-ng-model=location.locationName data-met-focus-on=loaded maxlength=64 tabindex=10 data-met-enter=save() ng-change=clearError()> <span data-ng-show="addLocationForm.$valid && !error" class=icon-check></span><p data-ng-if=error class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ modalMessages.placeExistsError.value }}</p><p data-ng-if=duplicate class="control-label help-block bottomless"></p></div></div><div class=modal-footer><button type=button class="btn btn-link" tabindex=2 data-ng-click="cancel(\'cancel btn\')">{{modalMessages.cancel.value}}</button> <button type=submit ng-disabled="location.locationName === undefined" class="btn btn-action-blue" tabindex=3 data-ng-click=save()>{{modalMessages.save.value}}</button></div></form></div>');
$templateCache.put('custom-modules/core/partials/_add-manufacturer-modal.html','<div class="modal-content add-options-modal-modal-shell" data-ng-init=vm.manufacturerInit()><div class=modal-header><h3>{{vm.manufacturerMessages.add.value}} {{vm.manufacturerMessages.addManufacturer.value}}</h3><i data-ng-if=vm.saving class="modal-spinner fa fa-spinner fa-spin"></i></div><form novalidate name=vm.addForm><div class=modal-body><div class=form-group><input type=text id=vm.addForm.manufacturer name=vm.addForm.manufacturer class=form-control required data-ng-model=vm.manufacturer.manufacturerName data-met-focus-on=loaded maxlength=64 tabindex=10 data-met-enter="vm.save(\'manufacturer\', vm.manufacturer)" data-ng-change=vm.clearError()> <span data-ng-show="vm.addForm.$valid && !vm.error" class=icon-check></span><p data-ng-if=vm.error class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ vm.error }}</p></div></div><div class=modal-footer><button class="btn btn-link" type=button ng-click="vm.cancel(\'cancel\')">{{vm.manufacturerMessages.cancel.value}}</button> <button type=submit data-ng-disabled="vm.manufacturer.manufacturerName === undefined" class="btn btn-action-blue" tabindex=12 ng-click="vm.save(\'manufacturer\', vm.manufacturer)">{{vm.manufacturerMessages.save.value}}</button></div></form></div>');
$templateCache.put('custom-modules/core/partials/_add-person-modal.html','<div class="modal-content add-options-modal-modal-shell" data-ng-init=personInit()><div class=modal-header><h3 class=modal-title>{{messages.add.value}} {{messages.addPerson.value}}</h3><div class=modal-spinner data-ng-show=saving><i class="fa fa-spinner fa-spin"></i></div></div><form novalidate name=addForm><div class=modal-body><div class=form-group><input type=text id=addForm.person name=addForm.person class=form-control required data-ng-model=person.personName data-met-focus-on=loaded maxlength=64 tabindex=10 data-met-enter="save(\'person\', person)" ng-change=clearError()> <span data-ng-show="addForm.$valid && !error" class=icon-check></span><p data-ng-if="duplicate || error" class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ error }}</p></div></div><div class=modal-footer><button type=button class="btn btn-link" tabindex=11 data-ng-click="cancel(\'cancelled on click\')">{{messages.cancel.value}}</button> <button type=submit data-ng-disabled="person.personName === undefined" class="btn btn-action-blue" tabindex=12 data-ng-click="save(\'person\', person)">{{messages.save.value}}</button></div></form></div>');
$templateCache.put('custom-modules/core/partials/_add-trade-modal.html','<div class="modal-content add-options-modal-modal-shell" data-ng-init=vm.tradeInit()><i data-ng-if=vm.saving class="modal-spinner fa fa-spinner fa-spin"></i><form novalidate name=vm.addForm><div class=modal-header><h3 class=modal-title>{{vm.tradeMessages.add.value}} {{vm.tradeMessages.addTrade.value}}</h3></div><div class=modal-body><div class=form-group><input type=text id=vm.addForm.trade name=vm.addForm.trade class=form-control required data-ng-model=vm.trade.divisionName data-met-focus-on=loaded maxlength=64 tabindex=1 data-met-enter="vm.save(\'trade\', vm.trade)" ng-change=vm.clearError()> <span data-ng-show="vm.addForm.$valid && !vm.error" class=icon-check></span><p data-ng-if=vm.error class="control-label help-block bottomless"><i class="icon icon-warning"></i>&nbsp; {{ vm.error }}</p></div></div><div class=modal-footer><button type=button class="btn btn-link" tabindex=11 data-ng-click="vm.cancel(\'cancel\')">{{vm.tradeMessages.cancel.value}}</button> <button type=submit data-ng-disabled="vm.trade.divisionName === undefined" class="btn btn-action-blue" tabindex=12 data-ng-click="vm.save(\'trade\', vm.trade)">{{vm.tradeMessages.save.value}}</button></div></form></div>');
$templateCache.put('custom-modules/core/partials/_general-error-modal.html','<div class="modal-content general-error-modal" data-ng-init=vm.generalErrorInit()><i data-ng-if=vm.saving class="modal-spinner fa fa-spinner fa-spin"></i><div class=general-error><div class=icon-construction-worker></div><div class=error-text><p>{{vm.generalErrorMessages.weAreSorry.value}}</p><p>{{vm.generalErrorMessages.generalErrorMessage.value}}</p></div><p class=inventory-buttons><a class=met-flat-button data-ng-click="vm.cancel(\'cancel\')">{{vm.generalErrorMessages.gotIt.value}}</a></p></div></div>');
$templateCache.put('custom-modules/core/partials/_places-add-person-modal.html','<div class=places-people-modal-box data-ng-init=placesAddPersonInit()><form name=addPersonForm><h5>{{messages.add.value}} {{newPersonName}}?</h5><p>{{messages.personWillBeAdded.value}} {{place.placeName}}</p><div class=action-buttons><md-button class=met-flat-button data-ng-click=cancel(messages.cancel.value)>{{ messages.cancel.value }}</md-button><md-button class=met-flat-button data-ng-click=saveAndContinue()>{{ messages.continue.value }}</md-button></div></form></div>');
$templateCache.put('custom-modules/core/partials/_places-check-duplicate-name-modal.html','<div class=places-people-modal-box data-ng-init=placesCheckDuplicateNameInit()><form name=checkDuplicateNameForm><h5>{{newPersonName}} {{messages.alreadyExists.value}}</h5><p>{{messages.assignExistingPerson.value}}</p><div class=action-buttons><md-button class=met-flat-button data-ng-click=cancel(messages.cancel.value)>{{ messages.cancel.value }}</md-button><md-button class=met-flat-button data-ng-click=assign()>{{ messages.assign.value }}</md-button></div></form></div>');
$templateCache.put('custom-modules/core/partials/_places-edit-name-modal.html','<div class=places-people-modal-box data-ng-init=placesEditNameInit()><form name=editNameForm><h4>{{messages.editName.value}}</h4><md-input-container id=container_{{place.placeId}}_{{personModel.personId}}><label>{{messages.name.value}}</label> <input id=name_{{place.placeId}}_{{personModel.personId}} required name=name data-ng-model=personModel.personName><div data-ng-messages=editNameForm.name.$error><div data-ng-message=required>{{messages.required.value}}</div></div></md-input-container><div data-ng-show=duplicate id=duplicate_{{place.placeId}}_{{personModel.personId}}>{{messages.name.value}} {{messages.alreadyExists.value}}</div><div class=action-buttons><md-button class=met-flat-button data-ng-click=cancel(messages.cancel.value)>{{ messages.cancel.value }}</md-button><md-button class=met-flat-button ng-disabled="editNameForm.$invalid || duplicate" data-ng-click=save()>{{ messages.save.value }}</md-button></div></form></div>');
$templateCache.put('custom-modules/place-migration/templates/placeMigration.html','<div class=place-darker-background data-ng-init=pmCtrl.initialize()><div class=row data-ng-cloak><div class=header-background id=locationsConvertTitle><label class=inventory-header><i ng-click=pmCtrl.backToPlaces() class="icon-arrow-left back-arrow"></i> {{pmCtrl.messages.locationsConvertWidget.value}}</label></div></div><div class=place-migration-intro-container><div class=place-migration-intro>{{pmCtrl.messages.placeMigrationIntro.value.format(pmCtrl.existingLocationsCount)}}</div><div class=place-migration-show-link ng-if=pmCtrl.showMore><md-button class=met-flat-button ng-click=pmCtrl.toggleShowMore(false)>{{pmCtrl.messages.showLess.value}}</md-button></div><div class=place-migration-show-link ng-if=!pmCtrl.showMore><md-button class=met-flat-button ng-click=pmCtrl.toggleShowMore(true)>{{pmCtrl.messages.showMore.value}}</md-button></div><div class=place-migration-intro-info ng-if=pmCtrl.showMore><div class=place-info-card><i class="place-project-card-icon icon-home"></i><p class=place-text-label>{{pmCtrl.messages.homeBase.value}}</p><p class=place-text-select-label>{{pmCtrl.messages.aboutHomeBase.value}}</p></div><div class=place-info-card id=searchCard><i class="place-project-card-icon icon-city"></i><p class=place-text-label>{{pmCtrl.messages.jobProject.value}}</p><p class=place-text-select-label>{{pmCtrl.messages.aboutProjectJob.value}}</p></div><div class=place-info-card><i class="place-project-card-icon icon-truck"></i><p class=place-text-label>{{pmCtrl.messages.vehicle.value}}</p><p class=place-text-select-label>{{pmCtrl.messages.aboutVehicle.value}}</p></div></div></div><div id=migration-container class=place-migration-control-container data-ng-cloak><div class=place-migration-control-header><div class=existing-location-header-number>{{pmCtrl.existingLocationsCount}}</div><div class=existing-location-header>{{pmCtrl.messages.existingLocations.value}}</div></div><div class=place-migration-control><div class=place-migration-control-select><div class=migration-select-place-container><div class=migration-number-label>1</div><md-input-container><md-select ng-model=pmCtrl.placeTypeToMigrateTo placeholder={{pmCtrl.messages.selectPlaceOption.value}}><md-option ng-repeat="placeType in pmCtrl.placeOptions" ng-value=placeType.placeTypeId>{{placeType.placeType.value}}</md-option></md-select></md-input-container></div><div class=migration-location-select-container><div class=migration-number-label>2</div><div>{{pmCtrl.messages.selectLocationsThatApply.value}}</div></div><div class=migration-location-select><div ng-repeat="place in pmCtrl.unspecifiedLocations"><md-checkbox ng-checked=pmCtrl.exists(place) ng-click=pmCtrl.toggleCheckBox(place)>{{ place.placeName }}</md-checkbox></div></div></div><div class=place-migration-control-confirm><div class=migration-location-confirm-container><div class=migration-number-label>3</div><div>{{pmCtrl.messages.confirmAndSubmit.value}}</div></div><div class=location-selection-count><div class=migration-selected-counter>{{pmCtrl.selectedLocations.length}}</div><div ng-if="pmCtrl.placeTypeToMigrateTo <= 1">{{pmCtrl.messages.locationsSelected.value}}</div><div ng-if="pmCtrl.placeTypeToMigrateTo === 2">{{pmCtrl.messages.totalProjectJob.value}}</div><div ng-if="pmCtrl.placeTypeToMigrateTo === 3">{{pmCtrl.messages.totalHomeBase.value}}</div><div ng-if="pmCtrl.placeTypeToMigrateTo === 4">{{pmCtrl.messages.totalVehicle.value}}</div></div><div class=migration-selected-locations-container><div class=migration-selected-locations ng-repeat="place in pmCtrl.selectedLocations"><i class="icon icon-check"></i><div class=comfirm-place-name>{{place.placeName}}</div></div></div><div class=migration-confirm-container><md-button ng-click=pmCtrl.migrate() ng-disabled="(pmCtrl.selectedLocations.length <= 0 || pmCtrl.placeTypeToMigrateTo <= 1)" class="met-flat-button primary">{{pmCtrl.messages.submit.value}}</md-button></div></div></div></div><div class=migration-back-to-places-link><a ng-click=pmCtrl.backToPlaces()>{{pmCtrl.messages.backToPlaces.value}}</a></div></div>');
$templateCache.put('directives/inventory/dashboard/metInventoryOverTimeGraph.directive.html','<div class=iot-graph data-ng-cloak><p><i class="icon icon-chart-growth"></i> <span>{{messages.inventoryOverTime.value}}</span></p><div class=date-range><label for=dateFrom class=range-text>{{messages.from.value}}</label> <input class=range-text id=dateFrom type=text data-ng-model=chartDateRange.start data-met-enter=dateChange()> <label for=dateTo class=range-text>{{messages.to.value}}</label> <input class=range-text id=dateTo type=text data-ng-model=chartDateRange.end data-met-enter=dateChange()></div><div id=inventoryOverTimeChartContainer></div></div>');
$templateCache.put('directives/inventory/dashboard/metToolsByCategoryGraph.directive.html','<div class=tbc-graph data-ng-cloak><p ng-if="currentSeriesDataObjects.length > 0"><i class="icon icon-chart-growth"></i> <span>{{messages.toolsByCategory.value}}</span></p><div id=toolsByCategoryChartContainer></div><div class=empty-categories-graph ng-if="currentSeriesDataObjects.length === 0"><i class="icon icon-wrench empty-place-graph-icon"></i><div class=subhead>{{messages.noItemsFound.value}}</div><div class=empty-place-graph-info>{{messages.noItemsForFilters.value}}</div></div></div>');
$templateCache.put('directives/inventory/bulkUpdate/metBulkUpdate.directive.html','<div class="bulk-update row slide-animation met-filters" data-ng-class="{ \'met-hide\': gridConfig.selectedFieldCount == 0 }"><div class=col-md-2><a data-ng-click=deselectAll()><i class="icon icon-circle-minus" aria-hidden=true></i> {{ gridConfig.selectedItemIds.length | number }} {{ messages.itemsSelected.value }}</a></div><div class="update-field col-md-8"><span>{{ messages.edit.value }}</span><ul><li data-ng-repeat="option in updateOptions" class=dropup><a class=dropdown-toggle data-toggle=dropdown>{{ option.name.value }}</a><div class=dropdown-menu data-ng-click=$event.stopPropagation()><ul><li data-ng-repeat="item in option.items" data-ng-click="update(option, item)" data-ng-class="{ \'is-updating\': isUpdating }">{{ item[option.nameProperty] }}</li></ul></div></li><li class=dropup><a class=dropdown-toggle data-toggle=dropdown>{{ messages.delete.value }}</a><div class=dropdown-menu data-ng-click=$event.stopPropagation()><ul><li data-ng-click=deleteSelectedItems() data-ng-class="{ \'is-updating\': isUpdating }">{{messages.deleteItems.value}}</li></ul></div></li></ul></div></div>');
$templateCache.put('directives/inventory/details/metDocuments.directive.html','<div id=item-detail-documents><div data-ng-if="item.modelNumber == \'2712-DE\' || item.modelNumber == \'2715-DE\' || item.modelNumber == \'2306-20\' || item.modelNumber == \'49-40-6105\'"><a data-ng-if="item.modelNumber == \'2712-DE\' || item.modelNumber == \'2715-DE\'" href=https://www.milwaukeetool.com/~/media/US/PDFs/Milwaukee%20HAMMERVAC%202715-DE_2712-DE%20Objective%20Data.pdf target=_blank>HAMMERVAC 2715-DE_2712-DE Objective Data..pdf</a> <a data-ng-if="item.modelNumber == \'2306-20\'" href=https://www.milwaukeetool.com/~/media/US/PDFs/Milwaukee%20HAMMERVAC%202306%20Objective%20Data.pdf target=_blank>HAMMERVAC 2306 Objective Data.pdf</a> <a data-ng-if="item.modelNumber == \'49-40-6105\'" href=https://www.milwaukeetool.com/~/media/US/PDFs/Milwaukee%2049-40-6105%20Objective%20Data.pdf target=_blank>49-40-6105 Objective Data.pdf</a></div><div class=status-message data-ng-if="item.modelNumber != \'2712-DE\' && item.modelNumber != \'2715-DE\' && item.modelNumber != \'2306-20\' && item.modelNumber != \'49-40-6105\'">{{ messages.noNotes.value }}</div></div>');
$templateCache.put('directives/inventory/details/metEditDetails.directive.html','<a data-toggle=modal data-ng-click=openDetails() data-target=#editItemDetails><i class="icon icon-pencil4"></i> {{ messages.editDetails.value }}</a><div id=editItemDetails class="modal fade item-modal" role=dialog><div class="modal-dialog add-new-item-container"><div class=modal-content data-ng-class="{ \'is-updating\': isUpdating }"><div class=modal-header>{{ messages.editToolDetails.value }} <i class="icon icon-cross close-modal" data-dismiss=modal data-ng-click=closeDetails(false) title="{{ messages.cancel.value }}"></i></div><div class=modal-body><form class=bootstrap-form data-ng-if=isLoaded name=detailForm><div class=row><div class="col-md-4 item-label"><met-image-thumb data-met-thumb-src=workingItem.imageAlternates.smallUrl data-met-detail-src=workingItem.imageAlternates.mediumUrl data-met-image-detail-position=right data-met-thumb-class=item-thumbnail-md data-met-thumb-default=workingItem.defaultImageUrl></met-image-thumb></div><div class=col-md-8><span class=item-label>{{ messages.toolPhoto.value }}</span><met-file-uploader data-ng-model=workingItem.imageUrl data-met-force-image=true data-met-model-alternates=workingItem.imageAlternates data-met-upload-url={{imageUploadUrl}}></met-file-uploader></div></div><div class=row><div class="col-md-4 item-label">{{ messages.toolNumber.value }}</div><div class=col-md-8><input type=text class=form-control name=toolNumber data-ng-model=workingItem.toolNumber maxlength=20></div></div><div class=row><div class="col-md-4 item-label">{{ messages.brand.value }}</div><div class=col-md-8><met-manufacturer-selector data-ng-model=workingItem.manufacturer data-met-manufacturers=itemFields.manufacturers data-met-on-manufacturer-added=itemFields.loadManufacturers()></met-manufacturer-selector></div></div><div class=row><div class="col-md-4 item-label">{{ messages.modelNumber.value }}</div><div class=col-md-8><input type=text class=form-control data-ng-model=workingItem.modelNumber maxlength=32></div></div><div class=row><div class="col-md-4 item-label">{{ messages.serialNumber.value }}</div><div class=col-md-8><input type=text class=form-control data-ng-model=workingItem.serialNumber data-ng-disabled="workingItem.isBluetoothCapable && workingItem.serialNumber != null && workingItem.serialNumberId > 0" maxlength=64></div></div><div class=row><div class="col-md-4 item-label">{{ messages.description.value }}</div><div class=col-md-8><textarea class=form-control data-ng-model=workingItem.itemDescription maxlength=256></textarea></div></div><div class=row><div class="col-md-4 item-label">{{ messages.category.value }}</div><div class=col-md-8><met-category-selector data-ng-model=workingItem.category data-met-categories=itemFields.categories data-met-on-category-added=itemFields.loadCategories()></met-category-selector></div></div><div class=row><div class="col-md-4 item-label">{{ messages.division.value }}</div><div class=col-md-8><met-trade-selector data-ng-model=workingItem.trade data-met-trades=itemFields.trades data-met-on-trade-added=itemFields.loadTrades()></met-trade-selector></div></div></form></div><div class=modal-footer><a data-dismiss=modal data-ng-click=closeDetails(true)>{{ messages.save.value }}</a> <a data-dismiss=modal data-ng-click=closeDetails(false)>{{ messages.cancel.value }}</a></div></div></div></div>');
$templateCache.put('directives/inventory/details/metFileUpload.directive.html','<div class=drop-box ngf-drop ngf-select ng-model=files ngf-drag-over-class=dragover ngf-multiple=true ngf-allow-dir=true accept=image/*,application/pdf ngf-pattern="\'image/*,application/pdf\'"><div><em class="icon icon-cloud-download upload-icon"></em></div><div>{{messages.dragAndDropUpload.value}}</div><div ngf-no-file-drop>File Drag/Drop is not supported for this browser</div><div class=drag-drop-browse>{{messages.browse.value}}</div></div>');
$templateCache.put('directives/inventory/details/metGeneralDetails.directive.html','<div class="col-md-5 add-new-item-container" id=item-general-info><div class="row item-general-info-header"><div class=col-md-4><div class=item-label>{{ messages.toolNumber.value }}</div><div class=tool-number>{{ item.toolNumber }}</div><met-image-thumb data-met-thumb-src=item.imageAlternates.smallUrl data-met-detail-src=item.imageAlternates.mediumUrl data-met-image-detail-position=right data-met-thumb-class=item-thumbnail-md data-met-thumb-default=defaultImage()></met-image-thumb></div><div class=col-md-8><div class=item-label>{{ item.manufacturer.manufacturerName }}</div><div>{{ item.modelNumber }}</div><div>{{ item.itemDescription }}</div><div class=serial-number>{{ item.serialNumber }}</div></div></div><form class="general-info bootstrap-form"><div class=row><div class="col-md-4 item-label bootstrap-valign-middle">{{ messages.location.value }}</div><div class=col-md-8><met-location-selector data-ng-model=item.location data-met-locations=locations data-met-on-location-added=loadItems()></met-location-selector></div></div><div class=row><div class="col-md-4 item-label bootstrap-valign-middle">{{ messages.person.value }}</div><div class=col-md-8><met-person-selector data-ng-model=item.person data-met-people=people data-met-on-person-added=loadItems()></met-person-selector></div></div><div class=row><div class="col-md-4 item-label bootstrap-valign-middle">{{ messages.status.value }}</div><div class=col-md-8><select data-ng-model=item.status class=form-control><option data-ng-repeat="status in statuses" data-ng-selected="item.status == status.statusId" value={{status.statusId}}>{{ status.statusName }}</option></select></div></div><div class=row data-ng-if=isLoaded><div class="col-md-4 item-label">{{ messages.serviceDate.value }}</div><div class=col-md-8><input type=text class="form-control date-control" id=detailServiceDate data-ng-model=serviceDateForPicker data-ng-blur=saveDatePicker() data-datetimepicker data-datetimepicker-options="{{ datePickerOptions }}"></div></div><div class=row data-ng-if=item.coinCellStatus><div class="col-md-4 item-label">{{ messages.coinCell.value }}</div><div class=col-md-8><span class=bold>{{ item.coinCellStatus }}%</span> <span class=item-label>{{ lastReportedDate }}</span></div></div></form></div>');
$templateCache.put('directives/inventory/details/metHistory.directive.html','<div id=item-detail-history data-ng-class="{\'centered\' : !isLoading && noHistory }"><div class=status-message data-ng-if=isLoading><i class="fa fa-spinner fa-spin"></i>{{ messages.historyLoading.value }}</div><div class=empty-history data-ng-if="!isLoading && noHistory"><p class="empty-state-icon large icon-history"></p><p class=content-empty-header>{{messages.weTrackForYou.value}}</p><p class=content-empty-message>{{messages.historyEmptyMessage.value}}</p><p class=history-empty-added>{{messages.toolAdded.value}} {{ dateAdded }} {{messages.at.value}} {{ timeAdded | date: \'shortTime\' }}</p></div><div class=left-aligned data-ng-if="!isLoading && !noHistory"><table id=toolHistoryTable class=tool-history-table data-ng-if=!noHistory><thead><tr><th>{{messages.date.value}}</th><th>{{messages.time.value}}</th><th>{{messages.place.value}}</th><th>{{messages.status.value}}</th><th class=tool-history-days>{{messages.totalDays.value}}</th></tr></thead><tbody><tr data-ng-repeat="history in historyList" class=tool-history-row><td>{{ history.changeDate }}</td><td>{{ history.changeTime | date: \'shortTime\' }}</td><td class=tool-history-location>{{ history.locationName }}</td><td>{{ history.status }}</td><td class=tool-history-days>{{ history.daysAt | number }}</td></tr></tbody></table></div></div>');
$templateCache.put('directives/inventory/details/metNotes.directive.html','<div id=item-detail-notes><div class=status-message data-ng-if=isLoading><i class="fa fa-spinner fa-spin"></i>{{ messages.loadingNotes.value }}</div><div data-ng-if="!isLoading && noNotes && !addNewNote"><p class="empty-state-icon medium icon-layers"></p><p class=content-empty-header>{{messages.makeANote.value}}</p><p class=content-empty-message>{{messages.emptyNotesText.value}}</p><p class=inventory-buttons><a class="met-action-button primary lone-button" data-ng-click=setNoteAdd(true)>{{ messages.addNote.value }}</a></p></div><div id=noteView data-ng-if="!editView && !addNewNote && !noNotes"><div class=notes-left-wrapper><div class=notes-left-column><div class=note-items data-ng-if="!isLoading && !noNotes"><div id=note.id data-ng-repeat="note in notes"><div data-ng-click=setSelectedNote(note.id)><p class=note-date>{{getLocalUtcDate(note.createdOn)}}</p><p class=note-wrap>{{note.text}}</p></div></div></div><button class="met-flat-button secondary note-add-button" data-ng-click=setNoteAdd(true)>{{ messages.addNote.value }}</button></div></div><div class=note-view-wrapper><div class=note-view data-ng-if="!isLoading && !noNotes"><div class=note-date-text><p>{{getLocalUtcDate(selectedNote.createdOn)}}</p><p class="note-text note-wrap">{{selectedNote.text}}</p></div><div class=action-buttons><md-button class=met-flat-button data-ng-click=setEdit(true)>{{ messages.edit.value }}</md-button><md-button class=met-flat-button data-met-confirm-popover=removeNote() data-met-placement=left data-met-confirm-message={{messages.deleteNoteMessage.value}} data-met-confirm-title={{messages.deleteNoteTitle.value}}>{{ messages.delete.value }}</md-button></div></div></div></div></div>');
$templateCache.put('directives/inventory/details/metNotesEdit.directive.html','<div class="edit-mode-container notes-edit" data-ng-if=addEditNote><div class=edit-mode-header><span data-ng-if=addNewNote>{{messages.addNote.value}}</span> <span data-ng-if=editView>{{messages.editNote.value}}</span></div><div class="form-inputs notes-form"><md-input-container md-no-float><div id=item-notes><textarea class=item-notes-text data-ng-if=addNewNote data-ng-model=newNote.text rows=11 md-maxlength=1000 maxlength=1000 aria-label={{messages.notes.value}}></textarea> <textarea class=item-notes-text data-ng-if=editView data-ng-model=selectedNote.text rows=11 md-maxlength=1000 maxlength=1000 aria-label={{messages.notes.value}}></textarea></div></md-input-container><p class=foot-note>{{messages.noteCharacterMax.value}}</p><div class=action-buttons data-ng-if=addNewNote><md-button class=met-flat-button data-ng-click=setNoteAdd(false)>{{ messages.cancel.value }}</md-button><md-button class=met-flat-button data-ng-click=saveNote()>{{ messages.save.value }}</md-button></div><div class=action-buttons data-ng-if=editView><md-button class=met-flat-button data-ng-click=setEdit(false)>{{ messages.cancel.value }}</md-button><md-button class=met-flat-button data-ng-click=saveEdit()>{{ messages.save.value }}</md-button></div></div></div>');
$templateCache.put('directives/inventory/details/metNotifications.directive.html','<div id=item-detail-notifications><div class=status-message data-ng-if=isLoading><i class="fa fa-spinner fa-spin"></i>{{ messages.loadingAlerts.value }}</div><div class=status-message data-ng-if="!isLoading && noNotifications">{{ messages.noAlerts.value }}</div><table data-ng-if="!isLoading && !noNotifications"><tr><th scope=col>{{ messages.read.value }}</th><th scope=col>{{ messages.dateReceived.value }}</th><th scope=col>{{ messages.alert.value }}</th><th scope=col></th></tr><tr data-ng-repeat="notification in notificationList" ng-class-even="\'notification-row-alt\'"><td class=center-align><i class="fa fa-circle-thin" data-ng-show=notification.acknowledgedOn></i> <i class="fa fa-circle" data-ng-show=!notification.acknowledgedOn data-ng-click="acknowledge(notification, $event)"></i></td><td class=notification-date><div>{{ getLocalUtcDate(notification.createdOn) }}</div><div>{{ getLocalUtcTime(notification.createdOn) }}</div></td><td class=notification-message><div class=notification-heading>{{ notification.heading }}</div><div>{{ notification.message }}</div><div><a data-ng-if=showServiceLink(notification.notificationType) data-ng-click=setStatusToService()>{{ messages.setToService.value }}</a></div></td><td><div data-ng-if=notification.isDismissable data-met-confirm-popover=dismiss(notification) data-met-confirm-message={{messages.deleteConfirm.value}} data-met-confirm-title={{messages.delete.value}} data-container=#grid-config data-met-placement=top><em class="icon icon-trash2 delete-alert"></em></div></td></tr></table></div>');
$templateCache.put('directives/inventory/details/metOverview.directive.html','<div class=item-detail-overview><div class=item-cycle-information data-ng-if=item.cycleInformation.lastSync><div class=cycles><div class=item-label>{{ messages.usage.value }}</div><div class=total-cycles-label>{{ item.cycleInformation.cyclesSinceLastService | number }}</div><div class=item-label>{{messages.cyclesSinceLastService.value}}</div></div><div class=cycles><div class=item-label>{{ messages.totalCycles.value }}</div><div class=total-cycles-label>{{ item.cycleInformation.totalCycles | number }}</div></div></div></div>');
$templateCache.put('directives/inventory/details/metPurchaseInfo.directive.html','<div class=purchase-info-container style=width:100%><div class=purchase-info><div id=purchaseView class=purchase-view data-ng-if="!editView && !emptyView"><div class=purchase-info-header>{{messages.purchaseInformation.value}}</div><div class=purchase-sub-header>{{messages.place.value}}</div><div class=purchase-info-field>{{item.purchaseLocation}}</div><div class=purchase-sub-header>{{messages.date.value}}</div><div class=purchase-info-field>{{item.datePurchased | date : \'shortDate\'}}</div><div class=purchase-sub-header>{{messages.itemValue.value}}</div><div class="purchase-info-field heavy">{{item.price }}</div><button class="btn btn-action-gray vline" data-ng-click="editPurchaseInformation(item, false)">{{ messages.edit.value }}</button></div><div class=purchase-view data-ng-if=emptyView><p class=content-empty-header>{{messages.saveForLaterConversational.value}}</p><p class=content-empty-message>{{messages.emptyPurchaseInfoText.value}}</p><p class=inventory-buttons><a class="met-action-button primary lone-button" data-ng-click="editPurchaseInformation(item, true)" id=add-from-empty>{{ messages.addInfo.value }}</a></p></div></div><div class=uploaded-docs-container><div class=uploaded-doc><label>{{ messages.orderInfo.value }}</label><div class=upload-input><met-image-thumb data-met-thumb-src=item.orderInformationImageAlternates.smallUrl data-met-detail-src=item.orderInformationImageAlternates.mediumUrl data-met-image-detail-position=right data-met-thumb-class=item-thumbnail-md></met-image-thumb><met-file-uploader data-ng-model=item.orderInformationImageUrl data-met-force-image=true data-met-model-alternates=item.orderInformationImageAlternates data-met-upload-allow-pdfs=true data-met-upload-url={{purchaseUploadUrl}}></met-file-uploader></div></div><div class=uploaded-doc><label>{{ messages.itemization.value }}</label><div class=upload-input><met-image-thumb data-met-thumb-src=item.itemizationImageAlternates.smallUrl data-met-detail-src=item.itemizationImageAlternates.mediumUrl data-met-image-detail-position=right data-met-thumb-class=item-thumbnail-md></met-image-thumb><met-file-uploader data-ng-model=item.itemizationImageUrl data-met-force-image=true data-met-model-alternates=item.itemizationImageAlternates data-met-upload-allow-pdfs=true data-met-upload-url={{purchaseUploadUrl}}></met-file-uploader></div></div></div></div>');
$templateCache.put('directives/inventory/details/metPurchaseInfoEdit.directive.html','<div class="edit-mode-container purchase-info-edit" data-ng-if=editView><div class=edit-mode-header><span data-ng-if=!addView>{{messages.editPurchaseInfo.value}}</span> <span data-ng-if=addView>{{messages.addPurchaseInfo.value}}</span></div><div class="form-inputs purchase-info-form"><div class="form-input category"><label>{{messages.purchaseDate.value}}</label> <input type=text id=purchaseDateInput class="form-control date-control item-detail-input" data-ng-model=purchaseDateForPicker data-datetimepicker data-datetimepicker-options={{datePickerOptions}}></div><md-input-container><label>{{messages.purchasePlace.value}}</label> <input data-ng-model=item.purchaseInfoEditLocation maxlength=64></md-input-container><md-input-container><label>{{messages.itemValue.value}}</label> <input type=text ng-keypress=isNumberKey($event) class=md-block data-ng-model=item.purchaseInfoEditValue></md-input-container><div class=action-buttons><md-button class=met-flat-button data-ng-click=cancel()>{{ messages.cancel.value }}</md-button><md-button class=met-flat-button data-ng-click=savePurchaseInfo();saveForm()>{{ messages.save.value }}</md-button></div></div></div>');
$templateCache.put('directives/inventory/details/metServiceRecordUpload.directive.html','<div ng-class="{\'drop-box\': !hasUploads, \'drop-box-upload\': hasUploads}" ngf-drop ngf-select ng-model=files ngf-drag-over-class=dragover ngf-multiple=true ngf-allow-dir=true accept=image/*,application/pdf ngf-pattern="\'image/*,application/pdf\'"><div data-ng-if=!hasUploads><em class="icon icon-cloud-download upload-icon"></em></div><div data-ng-if=!hasUploads>{{messages.dragAndDropUpload.value}}</div><div ngf-no-file-drop>File Drag/Drop is not supported for this browser</div><div class=drag-drop-browse data-ng-if=!hasUploads>{{messages.browse.value}}</div><div class=action-buttons data-ng-if=hasUploads><md-button class=met-flat-button data-ng-click=save(serviceRecord)>{{messages.upload.value}}</md-button></div></div>');
$templateCache.put('directives/inventory/details/metUploads.directive.html','<div id=item-detail-uploads class=upload-grid><div class=upload-container data-ng-if="uploads.length <= 0"><div><em class="empty-state-icon large icon-cloud-download"></em></div><div class=content-empty-header>{{messages.everythingInOneSpot.value}}</div><div class=content-empty-message>{{messages.emptyUploadsText.value}}</div></div><div class=upload-container data-ng-if="uploads.length > 0"><div class=upload-header>{{messages.uploadedItems.value}} ({{uploads.length}})</div><table class=upload-table><tr class=upload-row data-ng-repeat="uploadItem in uploads"><td>{{uploadItem.createdOnLocal | date:dateFormat}}</td><td><input id="{{uploadItem.resourceTitle + uploadItem.id}}" class=upload-title type=text readonly ng-dblclick=canEdit(uploadItem) data-ng-blur=update(uploadItem); data-ng-model=uploadItem.resourceTitle></td><td><a class=upload-view href={{uploadItem.resourceUrl}} target=_blank>{{messages.view.value}}</a></td><td><div data-ng-if=uploadItem.canDelete data-met-confirm-popover=delete(uploadItem.id) data-met-confirm-message={{messages.deleteConfirm.value}} data-met-confirm-title={{messages.delete.value}} data-container=#grid-config data-met-placement=top><i class="icon icon-trash2 upload-delete"></i></div></td></tr></table></div><div class=upload-browse><met-file-upload data-reload-items=loadUploads() data-item=item></met-file-upload></div></div>');
$templateCache.put('directives/inventory/filters/metBoolFilter.directive.html','<ul class=filter-item-list><li><label data-ng-click=modalChanged()><input type=radio name="filter_{{ filter.name }}" data-ng-model=filter.value data-ng-value=true> {{ boolMessages.yesLabel.value }}</label></li><li><label data-ng-click=modalChanged()><input type=radio name="filter_{{ filter.name }}" data-ng-model=filter.value data-ng-value=false> {{ boolMessages.noLabel.value }}</label></li></ul>');
$templateCache.put('directives/inventory/filters/metDateRangeFilter.directive.html','<ul class=filter-item-list><li><label data-ng-click=modalChanged()><input type=radio name="filter_{{ filter.name }}" data-ng-model=filter.value data-ng-value=7> {{ dateMessages.sevenDays.value }}</label></li><li><label data-ng-click=modalChanged()><input type=radio name="filter_{{ filter.name }}" data-ng-model=filter.value data-ng-value=30> {{ dateMessages.thirtyDays.value }}</label></li><li><label data-ng-click=modalChanged()><input type=radio name="filter_{{ filter.name }}" data-ng-model=filter.value data-ng-value=60> {{ dateMessages.sixtyDays.value }}</label></li><li><label data-ng-click=modalChanged()><input type=radio name="filter_{{ filter.name }}" data-ng-model=filter.value data-ng-value=90> {{ dateMessages.ninetyDays.value }}</label></li></ul>');
$templateCache.put('directives/inventory/filters/metFilters.directive.html','<div id=filterList><div class="arrow-up is-filters"></div><div class=available-filters><div class=slideDown-header><button class="met-action-button primary" data-ng-click=updateFilterResults() data-ng-disabled=!inventoryFilters.hasChanges data-ng-class="{ \'met-disabled\': !inventoryFilters.hasChanges }">{{ filterMessages.update.value }}</button> <button class="met-action-button secondary" data-ng-click=removeAllFilters() data-ng-disabled="inventoryFilters.selectedFilters <= 0 && !inventoryFilters.hasChanges" data-ng-class="{ \'met-disabled\': inventoryFilters.selectedFilters <= 0 && !inventoryFilters.hasChanges}">{{ filterMessages.clearAll.value }}</button></div><div data-ng-if=init><div id=filter-container><met-filter-selector data-met-filter=filters[0]></met-filter-selector><met-filter-selector data-met-filter=inventoryFilters.filters[6]></met-filter-selector><met-filter-selector data-met-filter=inventoryFilters.filters[3]></met-filter-selector><met-filter-selector data-met-filter=inventoryFilters.filters[4]></met-filter-selector><met-filter-selector data-met-filter=inventoryFilters.filters[2]></met-filter-selector><met-filter-selector data-met-filter=inventoryFilters.filters[13]></met-filter-selector><div class=filter-selector><div class=filter-header data-ng-click=showHideOneKeyFilter()>{{ filterMessages.oneKeyText.value }} <span class=symbol>{{oneKey.isOpened ? \'-\' : \'+\' }}</span></div><div class="filter-body slide-animation met-filters" data-ng-class="{\'met-hide\' : !oneKey.isOpened }"><ul class=filter-item-list><li class=filter-item><input id=chk_oneKeyOnly type=checkbox data-ng-model=inventoryFilters.oneKeyOnly data-ng-change=oneKeyOnlyChanged() data-ng-init=initialize()> <span data-ng-model=inventoryFilters.oneKeyOnly data-ng-click="oneKeyOnlyChanged(\'chk_oneKeyOnly\')" data-ng-class="{\'selected\' : inventoryFilters.oneKeyOnly === true }">{{ filterMessages.oneKeyOnlyText.value }}</span></li><li class=filter-item><input id=chk_tickOnly type=checkbox data-ng-model=inventoryFilters.tickOnly data-ng-change=tickOnlyChanged() data-ng-init=initialize()> <span data-ng-model=inventoryFilters.tickOnly data-ng-click="tickOnlyChanged(\'chk_tickOnly\')" data-ng-class="{\'selected\' : inventoryFilters.tickOnly === true }">{{ filterMessages.tickOnlyText.value }}</span></li></ul></div></div></div></div></div></div>');
$templateCache.put('directives/inventory/filters/metFilterSelector.directive.html','<div class=filter-selector><div class=filter-header data-ng-click=showHideFilter()><span>{{ filterLabel.value }}</span> <span class=symbol>{{filter.isOpened ? \'-\' : \'+\' }}</span></div><div class="filter-body slide-animation met-filters" data-ng-class="{\'met-hide\' : !filter.isOpened }"><met-item-filter data-ng-if="filter.filterType == \'list\'" data-filter=filter></met-item-filter><met-date-range-filter data-ng-if="filter.filterType == \'date\'"></met-date-range-filter><met-bool-filter data-ng-if="filter.filterType == \'bool\'"></met-bool-filter></div></div>');
$templateCache.put('directives/inventory/filters/metItemFilter.directive.html','<div><md-input-container data-ng-show="filter.items.length >= 10"><label>{{ messages.search.value }}</label> <input ng-model=searchText[filter.itemLabelProperty]></md-input-container><ul class=filter-item-list><li data-ng-repeat="item in filter.items | filter:searchText" data-ng-class="{\'filter-item\': !item.parentCategoryId, \'sub-filter-item\': item.parentCategoryId, \'disabled\': isDisabled(item[filter.itemIdProperty])}"><input id=status_{{item[filter.itemIdProperty]}} type=checkbox data-ng-model=item.isSelected data-ng-change=itemChange(item) data-ng-disabled=isDisabled(item[filter.itemIdProperty]) data-ng-init=initialize(item)> <span data-ng-click=labelClicked(item) data-ng-class="{\'disabled\' : isDisabled(item[filter.itemIdProperty]), \'selected\' : item.isSelected }">{{ item[filter.itemLabelProperty] }}</span></li></ul></div>');
$templateCache.put('directives/inventory/filters/metQuickFilters.directive.html','<div class=quick-filter-container><div class=quick-filter><input id=markedMissing type=checkbox data-ng-click=markedMissing()> <label for=markedmissing>{{filterMessages.markedMissing.value}}</label></div><div class=quick-filter><input id=unseen type=checkbox data-ng-click=unseen() data-ng-value=5> <i class="fa onekey-icon" title="{{ filterMessages.oneKeyItem.value }}"></i> <label for=unseen>{{filterMessages.unseen.value}}</label></div><div class=quick-filter><input id=hasUpcomingService type=checkbox data-ng-click=upcomingService()> <label for=hasUpcomingService>{{filterMessages.needsService.value}}</label></div><div class=quick-filter data-ng-hide=!enableGeofence><input id=outsideGeofence type=checkbox data-ng-click=outsideGeofence()> <label for=outsideGeofence>{{filterMessages.seenOutsideGeofence.value}}</label></div></div>');
$templateCache.put('directives/inventory/filters/metSelectedFilters.directive.html','<div class=selected-filters ng-show=selectedFilters.length><div class="animate-repeat met-filter-chip secondary" data-ng-repeat="selectedFilter in selectedFilters track by $index" data-ng-if="selectedFilter.isSaved && !selectedFilter.isQuickFilter"><span class=name>{{ selectedFilter.label }}</span> <span class=remove data-ng-click=quickRemoveFilter(selectedFilter) aria-hidden=true>X</span></div></div>');
$templateCache.put('directives/inventory/Grid/alertFrequency.html','<md-content id=mdcontentcontainer><md-card id=serviceAlertContainer class=md-padding layout=column style="box-sizing: content-box;"><section id=alertDatePicker data-ng-show="showDatePicker && !showFrequencyPicker" data-ng-model=workingDate><div id=serviceDatePicker></div></section><section id=alertFrequencyPicker data-ng-show="!showDatePicker && showFrequencyPicker" data-ng-model=workingAlertFrequency><p>{{ messages.recurringAlerts.value }}</p><form ng-submit=submit() ng-cloak><md-radio-group ng-model=selectedFrequency><div data-ng-repeat="option in alertFrequencyOptions"><md-radio-button value="{{ option }}" class=md-alert>{{ option }}</md-radio-button></div></md-radio-group></form></section><section id=alertFrequencyCTA layout=row layout-sm=column layout-align="center center" layout-wrap><button data-ng-show="!showDatePicker && showFrequencyPicker" data-ng-click=toggle() class="met-flat-button secondary">{{ messages.selectDate.value }}</button> <button data-ng-show="showDatePicker && !showFrequencyPicker" data-ng-click=toggle() class="met-flat-button secondary">{{ messages.repeats.value }}</button> <button class="met-flat-button md-primary" data-ng-click=toggle(true)>{{ messages.cancel.value }}</button> <button class=met-flat-button data-ng-click=submit()>{{ messages.save.value }}</button></section></md-card></md-content>');
$templateCache.put('directives/inventory/Grid/metAddEdit.directive.html','<div name=serviceRecordForm id=oneKeyAddEditContainer><div class="edit-mode-container service-edit" data-ng-init="isEdit = false;"><div class=edit-mode-header><div><span data-ng-if=!isEdit>{{messages.addRecordConversational.value}}</span> <span data-ng-if=isEdit>{{messages.editView.value}}</span></div></div><div class=edit-mode-fields><div class="form-inputs service-form"><div class="form-input category"><div class=service-date-type data-ng-if=!isEdit><label for=serviceDateInputAdd>{{ messages.serviceDate.value }}</label> <input type=text name=serviceDateInput id=serviceDateInputAdd class=form-control data-ng-model=serviceRecord.date data-datetimepicker data-datetimepicker-options={{datePickerOptions}} required></div><div class=service-date-type data-ng-if=isEdit><label for=serviceDateInputEdit>{{ messages.serviceDate.value }}</label> <input type=text name=serviceDateInput id=serviceDateInputEdit class=form-control data-ng-model=serviceRecord.date data-datetimepicker data-datetimepicker-options={{datePickerOptions}} required></div><div class=service-date-type><label for=serviceRecordType>{{messages.serviceType.value}}</label><select name=serviceRecordType id=serviceRecordType ng-options="type.name for type in serviceTypes track by type.id" ng-model=selectedType></select></div></div><md-input-container><label>{{ messages.servicedBy.value }}</label> <input type=text name=servicedBy data-ng-model=serviceRecord.servicedBy maxlength=32></md-input-container><md-input-container><label for=serviceRecordCostInput>{{ messages.cost.value }}</label> <input type=text id=serviceRecordCostInput name=serviceRecordCost ng-keypress=isNumberKey($event) data-ng-model=serviceRecord.cost maxlength=32></md-input-container><md-input-container md-no-float id=serviceRecordNote><div class=note-text-area><label for=serviceRecordNoteText>{{ messages.notes.value }}</label> <textarea id=serviceRecordNoteText class=note-text data-ng-model=serviceRecord.notes rows=4 md-maxlength=350 maxlength=350 aria-label={{messages.notes.value}}></textarea></div></md-input-container><p class=foot-note>{{messages.noteCharacterMax.value}}</p><div class=action-buttons><md-button class=met-flat-button data-ng-click=cancel()>{{ messages.cancel.value }}</md-button><md-button class=met-flat-button data-ng-click=save(serviceRecord)>{{ messages.save.value }}</md-button></div></div><div class=uploads-row><div class=edit-mode-display-browse data-ng-if=hasUploads><div class=attach-files-header>{{messages.attachFiles.value}}</div><div class=atttach-files-text>{{messages.attachText.value}}</div><table class=upload-table><caption class=upload-table-caption>{{messages.uploads.value}}</caption><tr class=upload-row data-ng-repeat="uploadItem in serviceRecord.serviceRecordUploads"><td>{{uploadItem.createdOnLocal | date:dateFormat}}</td><td><input class=upload-title type=text readonly ondblclick="this.readOnly=\'\';" data-ng-blur=update(uploadItem); data-ng-model=uploadItem.uploadTitle></td><td><a class=upload-view href={{uploadItem.uploadUrl}} target=_blank>{{messages.view.value}}</a></td><td><div data-met-confirm-popover=delete(uploadItem.id) data-met-confirm-message={{messages.deleteConfirm.value}} data-met-confirm-title={{messages.delete.value}} data-container=#grid-config data-met-placement=top><em class="icon icon-trash2 upload-delete"></em></div></td></tr></table></div><div ng-class="{\'edit-mode-browse\': !hasUploads, \'edit-mode-browse-right\': hasUploads}"><met-service-record-upload data-reload-items=refreshServiceRecords() data-item=serviceRecord data-has-uploads=hasUploads data-user-item=item data-selected-type=selectedType data-is-edit=isEdit></met-service-record-upload></div></div></div></div></div>');
$templateCache.put('directives/inventory/Grid/metGrid.directive.html','<div id=inventory-grid><table id=inventoryTable class=inventory-table data-ng-if=!loading cellpadding=0 cellspacing=0><thead id=tableHeader met-grid-headers data-refresh-grid=refreshGrid()></thead><tbody class=inventory-table-body data-ng-repeat="group in loadedGroups"><tr class="group-header inventory-table-row" data-ng-if="group.count > 0"><td class=quick-status><input type=checkbox data-ng-model=group.selected data-ng-click=selectGroupItems(group.id)></td><td colspan=15>{{ group.name }} ({{ group.count }})</td></tr><tr class=inventory-table-row met-grid-item data-ng-repeat-start="item in group.items" data-met-item=item data-met-group=group data-met-collapse-all=collapseAllItems() data-ng-class-odd="\'grid-alt-row\'"></tr><tr met-grid-item-details data-ng-repeat-end data-ng-if=item.isExpanded data-met-item=item data-ng-class-odd="\'grid-alt-row\'" data-tick-url={{tickUrl}}></tr></tbody></table><div class=inventory-empty-state data-ng-if="!loading && noInventory && !hasFilters && !hasSearchTerm"><i class="icon icon-hammer-wrench"></i><p class=content-empty-header>{{messages.noInventory.value}}</p><p class=content-empty-message><span>{{messages.emptyInventoryText.value}}</span></p><p class="inventory-buttons lone inventory-empty-add"><a class="met-action-button primary lone-button" ui-sref=add-options>{{ messages.addItemButton.value }}</a></p></div><div class=inventory-empty-state data-ng-if="!loading && noInventory && (hasFilters || hasSearchTerm)"><i class="icon icon-landscape"></i><p class=content-empty-header>{{messages.noResults.value}}</p><p class=content-empty-message><span>{{messages.noResultsForFilters.value}}</span></p><p class="inventory-buttons lone inventory-empty-add"><a class="met-action-button primary lone-button" ng-click=clearFilters()>{{ messages.clearFilters.value }}</a></p></div></div>');
$templateCache.put('directives/inventory/Grid/metGridConfig.directive.html','<div class=grid-settings><div class=show-column-selector><div class="settings-label dropdown-toggle" data-toggle=dropdown><i class="icon icon-cog" aria-hidden=true></i></div><div class="dropdown-menu pull-right"><div class=config-list-header><div><p class=title>{{messages.configureColumns.value}}</p><p class=guideline>{{messages.selectEightOptions.value}}</p></div><div class=arrow-container><span class=arrow-up></span></div></div><ul data-ng-if=!host.isEMEA() class=config-list data-ng-click=propagation($event)><li data-ng-repeat="column in columns"><input class=config-list type=checkbox data-ng-model=column.isVisible data-ng-click="changeColumns(column, column.isVisible, $event)" data-ng-disabled="defaultChecked == limitColumns && !column.isVisible" id="{{ column.label.value }}"> <span>{{ column.label.value }}</span></li></ul><ul data-ng-if=host.isEMEA() class=config-list-emea data-ng-click=propagation($event)><li data-ng-repeat="column in columns"><input class=config-list type=checkbox data-ng-model=column.isVisible data-ng-click="changeColumns(column, column.isVisible, $event)" data-ng-disabled="defaultChecked == limitColumns && !column.isVisible" id="{{ column.label.value }}"> <span>{{ column.label.value }}</span></li></ul></div></div></div>');
$templateCache.put('directives/inventory/Grid/metGridHeaders.directive.html','<thead><tr class=inventory-table-row><th class=quick-status><input type=checkbox data-ng-show="gridConfig.totalResults > 0" data-ng-model=gridConfig.allItemsSelected data-ng-click=selectAll()></th><th data-ng-repeat="header in headerValues" data-ng-click=setSortColumn(header) data-ng-show=header.isVisible data-ng-class="{ \'sorted-column\': header.isSorted }"><p>{{ header.label.value }} <i class="icon sort-direction" data-ng-class="{ \'icon-arrow-up\': header.isSorted && header.sortDescending, \'icon-arrow-down\': header.isSorted && !header.sortDescending }"></i></p></th><th><met-grid-config data-update-results=updateResults()></met-grid-config></th></tr></thead>');
$templateCache.put('directives/inventory/Grid/metGridItem.directive.html','<tr data-ng-click=expandGridItem() class="item-cells animate-element inventory-table-row" data-ng-class="{ \'item-expanded\': item.isExpanded, \'item-selected\': item.selected }"><td class=quick-status><div class=inventory-tdef-contents><input type=checkbox data-ng-model=item.selected data-ng-click=itemSelected($event)><div class=quick-status-alerts data-ng-if="item.alertCount > 0">{{ item.alertCount }}</div></div></td><td class=quick-status data-ng-if="showColumn(\'toolNumber\')"><p>{{ item.toolNumber | limitTo:25 }}</p></td><td class=quick-status data-ng-if="showColumn(\'description\')"><div class=inventory-tdef-contents><i class=fa data-ng-class="{\'onekey-icon\': item.isBluetoothCapable && item.itemInstanceId != null }" title="{{ messages.oneKeyItem.value }}"></i><div class=no-fa data-ng-if="!item.isBluetoothCapable || !item.itemInstanceId">&nbsp;</div><div class=item-description><div class=bold>{{ item.model | limitTo:25 }}</div><div class=truncate>{{ item.description }}</div></div></div></td><td class=quick-status data-ng-if="showColumn(\'serialNumber\')"><p>{{ item.serialNumber | limitTo:25 }}</p></td><td class=quick-status data-ng-if="showColumn(\'barcodeId\')"><p>{{ item.barcodeId | limitTo:25 }}</p></td><td class=quick-status data-ng-if="showColumn(\'manufacturer\')"><p>{{ item.manufacturer | limitTo:25 }}</p></td><td class=quick-status data-ng-if="showColumn(\'category\')"><p>{{ item.category | limitTo:25 }}</p></td><td class=quick-status data-ng-if="showColumn(\'place\')"><p>{{ item.place | limitTo:25 }}</p></td><td class=quick-status data-ng-if="showColumn(\'person\')"><p>{{ item.person | limitTo:25 }}</p></td><td class=quick-status data-ng-if="showColumn(\'trade\')"><p>{{ item.division | limitTo:25 }}</p></td><td class=quick-status data-ng-if="showColumn(\'status\')"><p>{{ item.status }}</p></td><td class=quick-status data-ng-if="showColumn(\'lastSeen\')"><p>{{ lastSeenDate | date:dateTimeFormat }}</p></td><td class=quick-status data-ng-if="showColumn(\'coinCell\')"><p>{{ item.coinCellStatus }}</p></td><td class=quick-status data-ng-if="showColumn(\'price\')"><p>{{ item.price }}</p></td><td class=quick-status data-ng-if="showColumn(\'purchaseDate\')"><p>{{ item.purchaseDate | date:dateFormat }}</p></td><td class=quick-status data-ng-if="showColumn(\'purchaseLocation\')"><p>{{ item.purchaseLocation | limitTo:25 }}</p></td><td class="table-cell-right quick-status"><i class=icon ng-class="item.isExpanded ? \'icon-chevron-up\' : \'icon-chevron-down\'"></i></td></tr>');
$templateCache.put('directives/inventory/Grid/metGridItemDetails.directive.html','<tr class="item-expanded inventory-table-row" data-ng-class="{ \'item-selected\': item.selected }"><td class=detail-cards colspan=15><div class=cards-container><div class=item-container id=itemDetails data-ng-if=!loading><md-tabs md-dynamic-height md-selected=tabSelectedIndex.index><md-tab label={{messages.itemDetails.value}} md-on-select=onTabChanges(0)><div class=detail-main><md-toolbar class=md-toolbar-tools><div class=detail-bar-select-item><p id=uisStatusLabel><span>{{messages.status.value}}</span><span class=arrow-down></span></p><ui-select data-ng-model=selectedStatus data-on-select="setSelectedStatus(selectedStatus, false)" search-enabled=false uis-open-close="onDropDownOpenClose(isOpen, this)" input-id=uisStatus><ui-select-match placeholder={{messages.searchOrAdd.value}} ng-model=$select.selected>{{$select.selected.statusName}}</ui-select-match><ui-select-choices position=down repeat="status in (statuses | filter: {\'statusName\': $select.search}) track by status.statusId"><span class=dropdown-options ng-bind-html="\'\'+ status.statusName| highlight: $select.search"></span></ui-select-choices><ui-select-no-choice><span class=add-option>{{messages.noResultsFound.value}}</span></ui-select-no-choice></ui-select><div class=select-box id=uisStatusSelect><p class=select-box-title><span>{{messages.status.value}}</span><span class=arrow-up></span></p></div></div><div class=detail-bar-select-item><p id=uisPlacesLabel><span>{{messages.place.value}}</span><span class=arrow-down></span></p><ui-select data-ng-model=selectedPlace.placeName uis-open-close="onDropDownOpenClose(isOpen, this)" input-id=uisPlaces><ui-select-match placeholder={{messages.searchOrAdd.value}} ng-model=$select.selected>{{$select.selected.placeName}}</ui-select-match><ui-select-choices group-by=firstLetterPlaceGroupFn group-filter=orderFilterFn position=down repeat="place.placeName as place in (locations | filter: {\'placeName\': $select.search}) track by place.placeId"><span class=dropdown-options ng-bind-html="\'\'+ place.placeName| highlight: $select.selected"></span></ui-select-choices><ui-select-no-choice><span class=add-option>{{messages.noResultsFound.value}}</span></ui-select-no-choice></ui-select><div class=select-box id=uisPlacesSelect><p class=select-box-title><span>{{messages.place.value}}</span><span class=arrow-up></span></p><button id=addPlace data-ng-click=triggerAddNewPlace(selectedPlace)>+</button></div></div><div class=detail-bar-select-item><p id=uisPersonsLabel><span>{{messages.person.value}}</span><span class=arrow-down></span></p><ui-select data-ng-model=selectedPerson.personName uis-open-close="onDropDownOpenClose(isOpen, this)" input-id=uisPersons><ui-select-match placeholder={{messages.searchOrAdd.value}} ng-model=$select.selected>{{$select.selected.personName}}</ui-select-match><ui-select-choices group-by=firstLetterPersonGroupFn group-filter=orderFilterFn position=down repeat="person.personName as person in (people | filter: {\'personName\': $select.search}) track by person.personId"><span class=dropdown-options ng-bind-html="\'\'+ person.personName | highlight: $select.search"></span></ui-select-choices><ui-select-no-choice><span class=add-option>{{messages.noResultsFound.value}}</span></ui-select-no-choice></ui-select><div class=select-box id=uisPersonsSelect><p class=select-box-title><span>{{messages.person.value}}</span><span class=arrow-up></span></p><button id=addPerson data-ng-click=triggerAddNewPerson(selectedPerson)>+</button></div></div><div class=detail-bar-select-item><p id=uisDivisionsLabel><span>{{messages.division.value}}</span><span class=arrow-down></span></p><ui-select data-ng-model=selectedDivision.divisionName uis-open-close="onDropDownOpenClose(isOpen, this)" input-id=uisDivisions><ui-select-match placeholder={{messages.searchOrAdd.value}} ng-model=$select.selected>{{$select.selected.divisionName}}</ui-select-match><ui-select-choices group-by=firstLetterDivisionGroupFn group-filter=orderFilterFn position=down repeat="division.divisionName as division in (trades | filter: {\'divisionName\': $select.search}) track by division.divisionId"><span class=dropdown-options ng-bind-html="\'\'+ division.divisionName | highlight: $select.search"></span></ui-select-choices><ui-select-no-choice><span class=add-option>{{messages.noResultsFound.value}}</span></ui-select-no-choice></ui-select><div class=select-box id=uisDivisionsSelect><p class=select-box-title><span>{{messages.division.value}}</span><span class=arrow-up></span></p><button id=addDivision data-ng-click=triggerAddNewDivision(selectedDivision)>+</button></div></div><div class=detail-bar-horizontal><div><i id=calendartarget class="icon icon-calendar-full"></i></div><div><span>{{messages.serviceDate.value}}</span><br><span ng-class="{\'service-date-alert\': itemDetails.hasServiceDateAlert}">{{ serviceDateByRegion }}</span></div><div><i id=serviceDateAndFrequency data-ng-if="item.serviceDate !== null && item.serviceAlertFrequency !== 0;" class=icon-alarm-ringing></i></div></div></md-toolbar></div><div class=detail-contents><div class="content-section item-stats"><img class=item-thumbnail data-ng-src={{itemDetails.imageAlternates.smallUrl}} onerror="this.src=\'/Content/images/placeholder_other.png\'"><div class=content-section-info><div class=tool-info><p class="featured-stat-message tool-number">{{messages.toolNumber.value}} {{itemDetails.toolNumber}}</p><p class=featured-stat-message>{{itemDetails.modelNumber}}</p><p class=featured-stat-message>{{itemDetails.itemDescription}}</p><p class=featured-stat-message>{{itemDetails.manufacturer.manufacturerName}}</p><p class=featured-stat-message data-ng-if=itemDetails.serialNumber>{{messages.itemSn.value}} {{itemDetails.serialNumber}}</p><p class=featured-stat-message data-ng-if=item.tickSerialNumber>{{messages.tickSn.value}} {{item.tickSerialNumber}}</p><p class=featured-stat-message data-ng-if=item.barcodeId>{{messages.barcode.value}} {{item.barcodeId}}</p></div><div class=cta-buttons><md-button class=met-flat-button data-ng-click=setEdit(true)>{{messages.edit.value}}</md-button><md-button class=met-flat-button data-ng-click=duplicateItem(itemDetails)>{{messages.duplicate.value}}</md-button></div></div></div><div class="content-section purchase-stats"><div class="content-section-info purchase-coin"><div class=pricing><p data-ng-if="itemDetails.price == null" class=inventory-buttons><a class="met-flat-button secondary lone-button" data-ng-click=onTabChanges(3)>{{ messages.purchaseInfo.value | uppercase }}</a></p><p data-ng-if="itemDetails.price != null" class=featured-stat-value data-ng-click=onTabChanges(3)>{{itemDetails.price | currency: ""}}</p><p data-ng-if="itemDetails.price != null" class=featured-stat-message>{{messages.itemValue.value}}</p></div><div><p class=featured-stat-message>{{messages.itemWasAdded.value}}</p><p class=featured-stat-time>{{timeFromEntry}}</p></div></div></div><div class="content-section coin-cell-stats" data-ng-if="(itemDetails.coinCellStatus > 0) || itemDetails.securityContext.isLocked || (!itemDetails.securityContext.isLocked && itemDetails.securityContext.shouldLock)"><div class="content-section-info purchase-coin"><div class=stats-section data-ng-if=itemDetails.securityContext.isLocked><p class=lock-status><em class="icon icon-lock lock-status"></em> {{messages.itemLocked.value}}</p></div><div class=stats-section data-ng-if="!itemDetails.securityContext.isLocked && itemDetails.securityContext.shouldLock"><p class=lock-status><em class="icon icon-unlock lock-status"></em> {{messages.pendingLock.value}}</p></div><div class=stats-section data-ng-if="itemDetails.coinCellStatus > 0"><p class=featured-stat-value>{{itemDetails.coinCellStatus}}%</p><p class=featured-stat-message>{{messages.coinCellLeft.value}}</p></div></div></div></div><div id=alertFrequency><alert-frequency service-date=itemDetails.serviceDate frequency=itemDetails.serviceAlertFrequency item-details=itemDetails item=item service-date-alert=serviceDateAlert></alert-frequency></div></md-tab><md-tab label={{messages.toolHistory.value}} md-on-select=onTabChanges(1)><met-history data-item=itemDetails></met-history></md-tab><md-tab label={{messages.serviceRecord.value}} md-on-select=onTabChanges(2)><met-service-record data-item=item></met-service-record></md-tab><md-tab label={{messages.resources.value}} md-on-select=onTabChanges(3)><md-toolbar class=md-toolbar-tools><div class=toggle-chips><div class=met-filter-chip ng-class="{\'secondary\': !purchaseInfoView}" ng-click="setResourcesView(true, false,false)"><span>{{messages.purchaseInfo.value}}</span></div><div class=met-filter-chip ng-class="{\'secondary\': !notesView}" ng-click="setResourcesView(false, true, false)"><span>{{messages.notes.value}}</span></div><div class=met-filter-chip ng-class="{\'secondary\': !uploadsView}" ng-click="setResourcesView(false, false, true)"><span>{{messages.uploads.value}}</span></div></div></md-toolbar><met-purchase-info data-item=itemDetails data-tab-selected-index=tabSelectedIndex.index data-save-item=saveForm() ng-show=purchaseInfoView class=ng-hide></met-purchase-info><met-notes data-item=itemDetails ng-show=notesView class=ng-hide></met-notes><met-uploads data-item=itemDetails ng-show=uploadsView class=ng-hide></met-uploads></md-tab><md-tab label={{messages.itemOverview.value}} data-ng-if=itemDetails.cycleInformation><met-overview data-item=itemDetails></met-overview><div class=last-sync-label>{{ messages.lastSync.value }}: {{ lastSyncDate | date:longDateTimeFormat }}</div></md-tab><md-tab><md-tab-label>{{messages.alerts.value}}<div class=quick-status-alerts-in-tab data-ng-if="item.alertCount > 0">{{ item.alertCount }}</div></md-tab-label><md-tab-body><met-notifications data-item=itemDetails data-user-item=item data-item-status=item.status data-save-item=saveForm() data-selected-status=selectedStatus data-statuses=statuses></met-notifications></md-tab-body></md-tab></md-tabs><div class=edit-mode-container ng-show=detailEditView><div class=edit-mode-header><span>{{messages.editItem.value}}</span></div><div class=form-upload-container><div class=form-inputs><div class="form-input category"><label>{{ messages.category.value }}</label><ui-select data-ng-model=itemDetails.category><ui-select-match placeholder={{messages.searchOrAdd.value}} ng-model=$select.selected>{{$select.selected.categoryName}}</ui-select-match><ui-select-choices group-by=firstLetterCategoryGroupFn group-filter=orderFilterFn position=down repeat="category in (categories | filter: {\'categoryName\': $select.search}) track by category.categoryId"><span class="dropdown-options search-dropdown" ng-bind-html="\'\'+ category.categoryName | highlight: $select.search"></span></ui-select-choices><ui-select-no-choice><span class=add-option>{{messages.noResultsFound.value}}</span></ui-select-no-choice></ui-select><label>{{ messages.manufacturer.value }}</label><ui-select data-ng-model=itemDetails.manufacturer ng-disabled="isValidModelNumber && itemDetails.manufacturer.isPrimary"><ui-select-match placeholder={{messages.searchOrAdd.value}} ng-model=$select.selected>{{$select.selected.manufacturerName}}</ui-select-match><ui-select-choices group-by=firstLetterManufacturerGroupFn group-filter=orderFilterFn position=down repeat="manufacturer in (manufacturers | filter: {\'manufacturerName\': $select.search}) track by manufacturer.manufacturerId"><span class="dropdown-options search-dropdown" ng-bind-html="\'\'+ manufacturer.manufacturerName | highlight: $select.search"></span></ui-select-choices><ui-select-no-choice><span class=add-option>{{messages.noResultsFound.value}}</span></ui-select-no-choice></ui-select></div><md-input-container><label>{{ messages.toolNumber.value }}</label> <input name=toolNumber data-ng-model=itemDetails.toolNumber maxlength=20></md-input-container><md-input-container id=modelNumberEditContainer ng-class="{\'md-input-invalid\': !itemDetails.modelNumber}"><label>{{ messages.modelNumber.value }}</label> <input data-ng-model=itemDetails.modelNumber maxlength=32></md-input-container><div id=modelNumberErrorMessage class=validation-error-message data-ng-show=!itemDetails.modelNumber>{{messages.requiredError.value}}</div><md-input-container id=serialNumberEditContainer><label>{{ messages.serialNumber.value }}</label> <input data-ng-model=itemDetails.serialNumber data-ng-disabled="itemDetails.isBluetoothCapable && itemDetails.serialNumber != null && itemDetails.serialNumberId > 0" maxlength=64></md-input-container><div id=serialNumberErrorMessage data-ng-show=updateError>{{errorMessage}}</div><md-input-container id=descriptionEditContainer ng-class="{\'md-input-invalid\': !itemDetails.itemDescription}"><label>{{ messages.description.value }}</label> <input data-ng-model=itemDetails.itemDescription maxlength=254></md-input-container><div id=descriptionErrorMessage class=validation-error-message data-ng-show=!itemDetails.itemDescription>{{messages.requiredError.value}}</div><div class=action-buttons><md-button class=met-flat-button data-ng-click="setEdit(false, true)">{{ messages.cancel.value }}</md-button><md-button class=met-flat-button data-ng-click=saveDetails() ng-disabled="!itemDetails.modelNumber || !itemDetails.itemDescription">{{ messages.save.value }}</md-button></div></div><div class=upload-input><met-image-thumb data-met-thumb-src=itemDetails.imageAlternates.smallUrl data-met-detail-src=itemDetails.imageAlternates.mediumUrl data-met-image-detail-position=right data-met-thumb-class=item-thumbnail-md data-met-thumb-default=itemDetails.defaultImageUrl></met-image-thumb><label>{{ messages.toolPhoto.value }}</label><met-file-uploader data-ng-model=itemDetails.imageUrl data-met-force-image=true data-met-model-alternates=itemDetails.imageAlternates data-met-upload-url={{imageUploadUrl}}></met-file-uploader></div></div></div></div><div class=map-container><div id=rightCard data-ng-if=!loading><div id=lastSeen><div class=map-information data-ng-if="itemDetails.lastSeen || itemDetails.hasTickAttached || itemDetails.lastScanned"><map class=google-map data-item=itemDetails fit=true></map><div class=seen-by-label>{{messages.seenByOneKey.value}}</div><div class=outside-geofence-warning ng-if=itemDetails.brokeGeofence><i class="icon icon-warning outside-geofence-warning-icon"></i> {{messages.outsideGeofence.value}}</div><div class=map-details><i class="last-seen-icon icon-barcode3" ng-if=isLatestScanned></i> <i class="last-seen-icon icon-map-marker" ng-if=!isLatestScanned></i> {{lastSeenText}}</div><div class=map-details>{{address}}</div></div><div class=map-empty data-ng-if="!itemDetails.lastSeen && !itemDetails.hasTickAttached && !itemDetails.lastScanned"><img class=map-empty-tick src=/Content/images/addTick.png alt={{messages.oneKey.value}}><div class=map-empty-header>{{messages.track.value}}</div><div class=map-empty-message>{{messages.trackMessage.value}}</div><a class=tick-learn-link ng-href={{tickUrl}} target=_blank>{{messages.learnMore.value}}</a> <em class="arrow-link icon-arrow-up-right"></em></div></div></div></div></div></td></tr>');
$templateCache.put('directives/inventory/Grid/metGridPaging.directive.html','<div class=paging-container data-ng-class="{ \'bottom-paging\': isBottom }" data-ng-hide="isBottom && (loading || totalResults == 0)"><div class=items-shown data-ng-if=!loading style="padding-left: 16px;"><form ng-submit=goTo() novalidate><span data-ng-if="totalResults > 0">{{ totalResults | number:0 }} <span class=small-text>{{ messages.tools.value | lowercase }}</span> <span><i class="fa fa-angle-left" aria-hidden=true data-ng-if="currentPage > 1" data-ng-click="goToPage(currentPage - 1)"></i> <input data-ng-if="totalPages > 1" id=pageNumber type=number ng-model=currentPage min=1 max={{totalPages}}> <span data-ng-if="totalPages <= 1">{{currentPage}}</span> <span>{{ messages.of.value }}</span> {{ totalPages| number:0 }} <i class="fa fa-angle-right" aria-hidden=true data-ng-if="totalPages > currentPage" data-ng-click="goToPage(currentPage + 1)"></i></span></span></form></div><div class=results-per-page><div class=per-page-label>{{ messages.resultsPerPage.value }}</div><md-select class=per-page-dropdown ng-model=resultsPerPage><md-option ng-value=resultOption ng-repeat="resultOption in resultsPerPageOptions" data-ng-click=changeResultsPerPage(resultOption)>{{ resultOption }}</md-option></md-select></div></div>');
$templateCache.put('directives/inventory/Grid/metGridResources.directive.html','<div style=width:100%><div class=purchase-info><div class=purchase-info-header>{{messages.purchaseInformation.value}}</div><div class=purchase-sub-header>{{messages.location.value}}</div><div class=purchase-info-field>{{item.purchaseLocation}}</div><div class=purchase-sub-header>{{messages.date.value}}</div><div class=purchase-info-field>{{item.datePurchased}}</div><div class=purchase-sub-header>{{messages.itemValue.value}}</div><div class=purchase-info-field>{{item.price}}</div></div><div style=width:50%></div></div>');
$templateCache.put('directives/inventory/Grid/metServiceRecord.directive.html','<div class=service-record-container ng-class="{centered: emptyServiceRecords}" id=serviceRecordContainer><div data-ng-if="serviceRecords.length > 0" class=left-aligned><table id=serviceRecordTable class=service-record-table data-ng-if="serviceRecords.length > 0"><thead><tr><th>{{messages.date.value}}</th><th>{{messages.serviceType.value}}</th><th>{{messages.cost.value}}</th><th>{{messages.servicedBy.value}}</th><th>{{messages.uploads.value}}</th><th></th><th></th></tr></thead><tbody><tr data-ng-repeat="record in serviceRecords" class=service-record-row><td>{{record.localDate }}</td><td>{{getTypeForRecords(record.typeId) }}</td><td>{{record.cost }}</td><td>{{record.servicedBy }}</td><td>{{record.serviceRecordUploads.length}}</td><td><a class=service-record-edit data-ng-click=editServiceRecord(record)>{{messages.view.value | uppercase}}</a></td><td><div data-met-confirm-popover=deleteServiceRecord(record.id) data-met-confirm-message={{messages.deleteConfirm.value}} data-met-confirm-title={{messages.delete.value}} data-container=#grid-config data-met-placement=top><i class="icon icon-trash2 service-record-row"></i></div></td></tr></tbody></table></div><p class="inventory-buttons align-right" data-ng-if="serviceRecords.length > 0"><a class="met-flat-button secondary" data-ng-click=addServiceRecord()>{{ messages.addServiceRecord.value }}</a></p><div data-ng-if=emptyServiceRecords><p class="empty-state-icon large icon-clipboard-check"></p><p class=content-empty-header>{{messages.everythingInOneSpot.value}}</p><p class=content-empty-message>{{messages.emptyServiceRecordText.value}}</p></div><p class=inventory-buttons data-ng-if=emptyServiceRecords><a class="met-action-button primary lone-button" data-ng-click=addServiceRecord()>{{ messages.createRecord.value }}</a></p></div>');
$templateCache.put('directives/reports/crimpers/metBasicInfo.directive.html','<div id=report-basic-info><h1 data-ng-show=!previewLoading>{{ infoMessages.basicInformation.value }}</h1><form name=crimperForm data-ng-show=!previewLoading novalidate><div class=row><div class=col-md-6><div class=form-group><label><span class=required>*</span> {{ infoMessages.companyName.value }}</label> <input type=text name=companyName class=form-control data-ng-model=companyInfo.companyName required maxlength=128> <span data-ng-show="showErrorMessage(crimperForm.companyName, \'required\')" class=error-block>{{ getRequiredValidation(infoMessages.companyName.value) }}</span></div><div class=form-group><label><span class=required>*</span> {{ infoMessages.country.value }}</label><select class=form-control name=countryCode data-ng-model=companyInfo.country data-ng-minlength=1 data-ng-required=true data-ng-options="country.code as country.name for country in countries" data-ng-change=updateStatesList()><option value>{{ infoMessages.selectFromList.value }}</option></select><span data-ng-show="showErrorMessage(crimperForm.countryCode, \'required\')" class=error-block>{{ getRequiredValidation(infoMessages.country.value) }}</span></div><div class=form-group><label><span class=required>*</span> {{ infoMessages.address.value }}</label> <input type=text class=form-control name=address1 data-ng-model=companyInfo.address1 maxlength=128 required> <span data-ng-show="showErrorMessage(crimperForm.address1, \'required\')" class=error-block>{{ getRequiredValidation(infoMessages.address.value) }}</span></div><div class=form-group><label><span class=required>*</span> {{ infoMessages.city.value }}</label> <input type=text class=form-control name=city data-ng-model=companyInfo.city maxlength=128 required> <span data-ng-show="showErrorMessage(crimperForm.city, \'required\')" class=error-block>{{ getRequiredValidation(infoMessages.city.value) }}</span></div><div class=form-group data-ng-if="statesByCountry.length > 1"><label><span class=required>*</span> {{ infoMessages.state.value }}</label><select id=stateList class=form-control name=stateCode data-ng-model=companyInfo.state data-ng-minlength=1 data-ng-required=true data-ng-options="state.code as state.name for state in statesByCountry"><option value>{{ infoMessages.selectFromList.value }}</option></select><span data-ng-show="showErrorMessage(crimperForm.stateCode, \'required\')" class=error-block>{{ getRequiredValidation(infoMessages.state.value) }}</span></div><div class=form-group><label><span class=required>*</span> {{ infoMessages.zip.value }}</label> <input type=text class=form-control name=zip data-ng-model=companyInfo.zip maxlength=16 required> <span data-ng-show="showErrorMessage(crimperForm.zip, \'required\')" class=error-block>{{ getRequiredValidation(infoMessages.zip.value) }}</span></div><div class=form-group><label>{{ infoMessages.phoneNumber.value }}</label> <input type=text class=form-control data-ng-model=companyInfo.phone maxlength=20></div><div class=form-group><label>{{ infoMessages.faxNumber.value }}</label> <input type=text class=form-control data-ng-model=companyInfo.fax maxlength=20></div><div class=form-group><label>{{ infoMessages.website.value }}</label> <input type=text class=form-control data-ng-model=companyInfo.website maxlength=128></div><div class=form-group><label>{{ infoMessages.logo.value }}</label><div><met-image-thumb data-met-thumb-src=companyInfo.imageAlternates.smallUrl data-met-detail-src=companyInfo.imageAlternates.mediumUrl data-met-image-detail-position=right data-met-thumb-class=item-thumbnail-md></met-image-thumb><span class=item-label>{{ messages.toolPhoto.value }}</span><met-file-uploader data-ng-model=companyInfo.companyLogo data-met-force-image=true data-met-model-alternates=companyInfo.imageAlternates data-met-upload-url={{imageUploadUrl}}></met-file-uploader></div></div><div class=form-group><label><input type=checkbox data-ng-model=saveCompanyInfo> {{ infoMessages.saveComanyInfo.value }}</label></div></div><div class=col-md-6><div class=form-group><label><span class=required>*</span> {{ infoMessages.jobName.value }}</label> <input type=text name=jobName class=form-control data-ng-model=jobName maxlength=128 required> <span data-ng-show="showErrorMessage(crimperForm.jobName, \'required\')" class=error-block>{{ getRequiredValidation(infoMessages.jobName.value) }}</span></div><div class=form-group><label><span class=required>*</span> {{ infoMessages.operator.value }}</label> <input type=text name=operator class=form-control data-ng-model=operator maxlength=128 required> <span data-ng-show="showErrorMessage(crimperForm.operator, \'required\')" class=error-block>{{ getRequiredValidation(infoMessages.operator.value) }}</span></div><div class=form-group><label>{{ infoMessages.customer.value }}</label> <input type=text class=form-control data-ng-model=customer maxlength=128></div><div class=form-group><label>{{ infoMessages.notes.value }}</label> <textarea class=form-control data-ng-model=notes maxlength=256>\r\n                </textarea></div><div class=form-group><label>{{ infoMessages.units.value }}</label><div class=units><label><input type=checkbox data-ng-model=isPsi> {{ infoMessages.unitsPsi.value }}</label> <label><input type=checkbox data-ng-model=isBar> {{ infoMessages.unitsBar.value }}</label></div></div></div></div><h1 data-ng-if="crimperIncidents.length > 0">{{ infoMessages.lowPressureIncidents.value }}</h1><div data-ng-repeat="crimperIncident in crimperIncidents" class=item-incident data-ng-class="{ \'alt-row\': $even }"><div class=item-description>{{ crimperIncident.crimper.itemDescription }}</div><div class=item-serial-model>{{ crimperIncident.crimper.serialNumber }} <i class="fa fa-circle" aria-hidden=true></i> {{ crimperIncident.crimper.modelNumber }}</div><div class=row><div class=col-md-6><div data-ng-repeat="incident in crimperIncident.incidents" data-ng-if=$even class=form-group><label>{{ infoMessages.cycleNumber.value }}{{ incident.toolIndex }} <i class="fa fa-circle" aria-hidden=true></i> {{ getLocalDate(incident.recordedOn) }} <i class="fa fa-circle" aria-hidden=true></i> {{ infoMessages.maxPressure.value }} {{ incident.peakPressure }} {{ infoMessages.unitsPsi.value }}</label> <input type=text class=form-control data-ng-model=incident.notes maxlength=128></div></div><div class=col-md-6><div data-ng-repeat="incident in crimperIncident.incidents" data-ng-if=$odd class=form-group><label>{{ infoMessages.cycleNumber.value }}{{ incident.toolIndex }} <i class="fa fa-circle" aria-hidden=true></i> {{ getLocalDate(incident.recordedOn) }} <i class="fa fa-circle" aria-hidden=true></i> {{ infoMessages.maxPressure.value }} {{ incident.peakPressure }} {{ infoMessages.unitsPsi.value }}</label> <input type=text class=form-control data-ng-model=incident.notes maxlength=128></div></div></div></div><button type=button class="btn btn-action-blue" data-ng-click=previewReport()>{{ infoMessages.previewReport.value }}</button></form><div class=status-message data-ng-if=previewLoading><i class="fa fa-spinner fa-spin"></i>{{ infoMessages.loadingReport.value }}</div></div>');
$templateCache.put('directives/reports/crimpers/metCrimpersList.directive.html','<table class=inventory-table><thead><tr><th class=align-center><input type=checkbox data-ng-model=allSelected data-ng-change=allSelectedChange()></th><th class=align-left data-ng-class="{ \'sorted-column\': sortColumn == \'serialNumber\' }">{{ messages.serialNumber.value }} <i class="icon sort-direction icon-arrow-down" data-ng-if="sortColumn == \'serialNumber\' && !isDescending"></i> <i class="icon sort-direction icon-arrow-up" data-ng-if="sortColumn == \'serialNumber\' && isDescending"></i></th><th class=align-left data-ng-class="{ \'sorted-column\': sortColumn == \'description\' }">{{ messages.description.value }} <i class="icon sort-direction icon-arrow-down" data-ng-if="sortColumn == \'description\' && !isDescending"></i> <i class="icon sort-direction icon-arrow-up" data-ng-if="sortColumn == \'description\' && isDescending"></i></th><th class=align-left data-ng-class="{ \'sorted-column\': sortColumn == \'location\' }">{{ messages.place.value }} <i class="icon sort-direction icon-arrow-down" data-ng-if="sortColumn == \'location\' && !isDescending"></i> <i class="icon sort-direction icon-arrow-up" data-ng-if="sortColumn == \'location\' && isDescending"></i></th><th class=align-center data-ng-class="{ \'sorted-column\': sortColumn == \'totalCycles\' }">{{ messages.totalCycles.value }} <i class="icon sort-direction icon-arrow-down" data-ng-if="sortColumn == \'totalCycles\' && !isDescending"></i> <i class="icon sort-direction icon-arrow-up" data-ng-if="sortColumn == \'totalCycles\' && isDescending"></i></th><th class=align-center data-ng-class="{ \'sorted-column\': sortColumn == \'cyclesSinceService\' }">{{ messages.cyclesSinceService.value }} <i class="icon sort-direction icon-arrow-down" data-ng-if="sortColumn == \'cyclesSinceService\' && !isDescending"></i> <i class="icon sort-direction icon-arrow-up" data-ng-if="sortColumn == \'cyclesSinceService\' && isDescending"></i></th><th class=align-left data-ng-class="{ \'sorted-column\': sortColumn == \'lastSync\' }">{{ messages.lastSync.value }} <i class="icon sort-direction icon-arrow-down" data-ng-if="sortColumn == \'lastSync\' && !isDescending"></i> <i class="icon sort-direction icon-arrow-up" data-ng-if="sortColumn == \'lastSync\' && isDescending"></i></th><th class=align-center data-ng-class="{ \'sorted-column\': sortColumn == \'coinCell\' }">{{ messages.coinCell.value }} <i class="icon sort-direction icon-arrow-down" data-ng-if="sortColumn == \'coinCell\' && !isDescending"></i> <i class="icon sort-direction icon-arrow-up" data-ng-if="sortColumn == \'coinCell\' && isDescending"></i></th></tr></thead><tbody><tr data-ng-repeat="item in results" data-ng-class-odd="\'grid-alt-row\'"><td class=align-center><input type=checkbox data-ng-model=item.selected data-ng-change=selectionChange()></td><td class=align-left>{{ item.serialNumber }}</td><td class=align-left>{{ item.itemDescription }}</td><td class=align-left>{{ item.place.locationName }}</td><td class=align-center>{{ item.totalEventCount | number }}</td><td class=align-left>{{ item.eventsSinceLastService | number}}</td><td class=align-left>{{ item.lastEventSetCreatedOn | date:dateFormat }}</td><td class=align-center>{{ item.coinCellStatus }}<span data-ng-if=item.coinCellStatus>%</span></td></tr></tbody></table>');
$templateCache.put('directives/reports/crimpers/metLocations.directive.html','<div><div class=arrow-up></div><div class=available-categories><div class="crimper-report-slideDown-header row"><i class="icon icon-cross" aria-hidden=true data-ng-click=showHideLocations()></i></div><div class=row><div class=col-md-4><ul class=category-list><li data-ng-repeat="location in itemFields.locations" data-ng-if="$index <= firstColumnEnd" data-ng-click=locationClick(location) data-ng-class="{ \'category-selected\': location.isSelected }"><div class=category-name>{{ location.placeName }}</div></li></ul></div><div class=col-md-4><ul class=category-list><li data-ng-repeat="location in itemFields.locations" data-ng-if="$index > firstColumnEnd && $index <= secondColumnEnd" data-ng-click=locationClick(location) data-ng-class="{ \'category-selected\': location.isSelected }"><div class=category-name>{{ location.placeName }}</div></li></ul></div><div class=col-md-4><ul class=category-list><li data-ng-repeat="location in itemFields.locations" data-ng-if="$index > secondColumnEnd" data-ng-click=locationClick(location) data-ng-class="{ \'category-selected\': location.isSelected }"><div class=category-name>{{ location.placeName }}</div></li></ul></div></div></div></div>');
$templateCache.put('directives/reports/crimpers/metPreviewReport.directive.html','<div id=preview-report><div class=preview-report-header><h1>{{ previewMessages.previewReport.value }}</h1><button type=button class="btn btn-action-blue" data-ng-click=downloadReport()>{{ previewMessages.downloadPdf.value }}</button></div><div ng-bind-html=reportHtml class=pdf-report></div></div>');
$templateCache.put('directives/reports/crimpers/metSelectCrimpers.directive.html','<div><div class=content-header><div class="col-md-6 content-header-title report-header-title"><h4>{{messages.hydraulicReports.value}}</h4></div><div class="col-md-4 search-box" style=border:none><i class="icon icon-magnifier"></i> <input type=text data-ng-model=searchTerm placeholder="{{ messages.inventorySearch.value }}" data-ng-keyup=searchKeyUp($event)></div><div class="col-md-2 add-inventory"><a data-ng-click=enterInfo() data-ng-if=showGenerateReport()><i class="icon icon-chart-growth" aria-hidden=true></i>{{ messages.addInventory.value }}</a></div></div><div id=grid-config><div class="filters-link animate-element" data-ng-click=showHideLocations() data-ng-class="{ \'filters-expanded\': locationsExpanded }" style=justify-content:flex-start><i class="icon icon-map-marker" aria-hidden=true></i> {{ messages.placesDropDown.value }} <i class="icon icon-chevron-down" data-ng-class="{ \'icon-chevron-up\': filtersExpanded, \'icon-chevron-down\': !filtersExpanded }" aria-hidden=true></i></div><div id=date-filters><div class=row><div class=col-md-2><label>{{ messages.startLabel.value }}:</label></div><div class=col-md-4><input type=text class="form-control date-control" data-ng-model=startDate data-datetimepicker data-met-datetimepicker-max=endDateMax data-datetimepicker-options="{{ datePickerOptions }}"></div><div class=col-md-2><label>{{ messages.endLabel.value }}:</label></div><div class=col-md-4><input type=text class="form-control date-control" data-ng-model=endDate data-datetimepicker data-datetimepicker-options="{{ datePickerOptions }}" data-met-datetimepicker-max=endDateMax data-ng-change=endDateChange()></div></div></div></div><met-locations class="slide-animation met-filters" data-ng-class="{\'met-hide\' : !locationsExpanded}" data-update-results=updateResults() data-show-hide-locations=showHideLocations()></met-locations><div class=status-message data-ng-if=loading><i class="fa fa-spinner fa-spin"></i>{{ messages.loadingHydraulics.value }}</div><div class=status-message data-ng-if="!loading && noCrimpers" data-ng-cloak>{{ messages.hydraulicsEmpty.value }}</div><met-crimpers-list data-results=crimpers data-ng-if="!loading && !noCrimpers" data-sort-column=sortedColumn data-is-descending=isDescending></met-crimpers-list></div>');}]);
(function() {
    'use strict';

    var app = angular.module('oneKeyApp');
    var maintenanceService = function ($http, $q, urls, host) {
        var service = {
            getMaintenanceStatus: getMaintenanceStatus,
            parseMessage: parseMessage
        };

        function getMaintenanceStatus() {
            var url = urls('maintenanceModeApi') + '/?platform=2';
            var deferred = $q.defer();
            $http.get(url)
                .success(deferred.resolve)
                .error(deferred.reject);

            return deferred.promise;
        }

        function parseMessage(response) {
            if (!response) {
                return null;
            }
            if (response.overrideMessage && !host.isANZ()) {
                return response.overrideMessage;
            }
            if (!(moment(response.scheduledMaintenance.displayMessageStart).format() <= moment.utc().format() &&
                moment(response.scheduledMaintenance.displayMessageEnd).format() >= moment.utc().format())) {
                return null;
            }
            var hasSeenMessage = localStorage.getItem('shownMaintenanceMessage' + response.scheduledMaintenance.id);
            if (!hasSeenMessage) {
                var messageFormat = response.scheduledMaintenance.scheduledMaintenanceMessage;
                var message = messageFormat.replace("{startDate}", moment(response.scheduledMaintenance.start).local().format('lll'));
                message = message.replace("{endDate}", moment(response.scheduledMaintenance.end).local().format('lll'));
                return message;
            }
        }

        return service;
    };
    
    app.service('maintenanceService', maintenanceService);
    maintenanceService.$inject = ['$http', '$q', 'urls', 'host'];

}());
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metDatetimepickerMax', function () {
        return {
            restrict: 'AE',
            link: function (scope, element, attrs) {
                var maxDateName = attrs.metDatetimepickerMax;

                scope.$watch(maxDateName, function (val) {
                    var datePicker = $(element).data('DateTimePicker');
                    if (val && moment(val).isValid()) {
                            datePicker.maxDate(val);
                    } else {
                        datePicker.maxDate(false);
                    }
                });
            }
        };
    });
}());
(function() {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metDatetimepickerMin', function() {
        return {
            restrict: 'AE',
            link: function(scope, element, attrs) {
                var minDateName = attrs.metDatetimepickerMin;

                scope.$watch(minDateName, function (val) {
                    var datePicker = $(element).data('DateTimePicker');
                    if (val && moment(val).isValid()) {
                        if (moment(val) < datePicker.minDate()
                            || !datePicker.minDate()) {
                            datePicker.minDate(val);
                        }
                    } else {
                        datePicker.minDate(false);
                    }
               });
            }
        };
    });
}());
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metFadeOut', function () {
        return {
            restrict: 'A',
            link: function (scope, elm, attrs) {
                var duration = parseInt(attrs.metFadeOut);
                if (isNaN(duration)) {
                    duration = 600;
                }
                elm = jQuery(elm);
                //elm.hide();
                //elm.fadeIn(duration)
                scope.destroy = function (complete) {
                    elm.animate({ opacity: 0 }, duration, function () {
                        if (complete) {
                            scope.$apply(complete);
                        }
                    });
                };
            }
        };
    });

    oneKeyApp.directive('metFadeOutSlideUp', function () {
        return {
            restrict: 'A',
            link: function (scope, elm, attrs) {
                var duration = parseInt(attrs.metFadeOut);
                if (isNaN(duration)) {
                    duration = 600;
                }
                elm = jQuery(elm);
                //elm.hide();
                //elm.fadeIn(duration)

                scope.destroy = function (complete) {
                    elm.animate({ opacity: 0 }, duration / 2).slideUp(duration / 2, function () {
                        if (complete) {
                            scope.$apply(complete);
                        }
                    });
                };
            }
        };
    });

    oneKeyApp.service('fadeOut', function () {
        return function (scope, callback) {
            if (scope.destroy) {
                scope.destroy(callback);
            }
        };
    }
    );
}());

(function() {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metConfirmPopover', [
        '$compile', 'localize', function($compile, metLocalize) {
            var popoverTemplate =
                '<p>{{metConfirmMessage}}</p>' +
                    '<div class="popover-footer">' +
                    '<button type="button" class="btn btn-action-blue" ng-click="ok()" data-met-stop-event="click">{{messages.ok.value}}</button>' +
                    '<button type="button" class="btn btn-default" ng-click="cancel()" data-met-stop-event="click">{{messages.cancel.value}}</button>' +
                    '</div>';

            return {
                restrict: "A",
                link: function(scope, element, attrs) {
                    var popOverContent;

                    scope.messages = {
                        ok: metLocalize('commands', 'ok'),
                        cancel: metLocalize('commands', 'cancel')
                    };

                    popOverContent = $compile(popoverTemplate)(scope);
                    var popupPlacement = attrs.metPlacement ? attrs.metPlacement : "left";
                    var options = {
                        content: popOverContent,
                        placement: popupPlacement,
                        html: true,
                        title: scope.metConfirmTitle,
                        trigger: 'click'
                    };
                    jQuery214(element).popover(options);
                    scope.ok = function() {
                        jQuery214(element).popover('hide');
                        scope.metConfirmPopover();
                    }
                    scope.cancel = function(e) {
                        jQuery214(element).popover('hide');
                    };
                    scope.$on('$destroy', function() {
                        jQuery214(element).popover('destroy');
                    });

                    jQuery214(element).on('show.bs.popover', function () {
                        jQuery214('.popover').popover('hide');
                    })

                    // custom event to force a 
                    element.bind('dynamic_show', function (e) {
                        jQuery214(element).popover('show');
                    });
                },
                scope: {
                    metConfirmMessage: '@',
                    metConfirmTitle: '@',
                    metConfirmPopover: '&'
                }
            };
        }
    ]);
}());

(function() {
    'use strict';


    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metEnter', function() {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                element.bind("keydown keypress", function(event) {
                    if (event.which === 13) {
                        scope.$apply(function() {
                            scope.$eval(attrs.metEnter);
                        });

                        event.preventDefault();
                    }
                });
            }
        };
    });
}());
(function () {
    'use strict';

    var app = angular.module('oneKeyApp');

    app.service('notifications', ['$resource', 'urls', function ($resource, metUrls) {
            var acknowledged = 0;       // tracks the number of notifications that have been acknowledged.

            var resource = $resource(metUrls('notificationsApi').concat('/:notificationId'),
                {
                    notificationId: '@notificationId'
                },
                {
                    'dismiss': { method: 'DELETE' },
                    'itemNotifications': { 
                        method: 'GET', 
                        url: metUrls('notificationsApi').concat('/item/:userItemId'),
                        params: {
                            userItemId: '@userItemId'
                        }
                    },
                    'acknowledge': { method: 'PUT' },
                    'getNewCount': { method: 'GET', url: metUrls('notificationsApi').concat('/count') }
                }
            );

            return {
                getAll: function (successCallback, errorCallback) {
                    return resource.get(successCallback, errorCallback);
                },
                getItemNotifications: function (itemId, successCallback, errorCallback) {
                    return resource.itemNotifications({ userItemId: itemId }, successCallback, errorCallback);
                },
                getSummary: function (successCallback, errorCallback) {
                    return resource.getNewCount(successCallback, errorCallback);
                },
                acknowledge: function (notification, successCallback, errorCallback) {
                    return resource.acknowledge({ notificationId: notification.id }, successCallback, errorCallback);
                },
                dismiss: function (id, successCallback, errorCallback) {
                    return resource.dismiss({ notificationId: id }, successCallback, errorCallback);
                },
                getInventoryUrl: function (id) {
                    return metUrls('inventory') + '/' + id;
                }
            };
        }
    ]);
}());
(function () {
    'use strict';

    angular.module('oneKeyApp.placeAdd', [
            'ngCookies', 'ngSanitize', 'ngFileUpload', 'ngAnimate'
        ])
        .config(['$httpProvider', function ($httpProvider) {
                if (localStorage.getItem('access_token')) {
                    $httpProvider.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('access_token');
                }

                $httpProvider.interceptors.push(function ($q) {
                    return {
                        responseError: function (response) {
                            return $q.reject(response);
                        }
                    };
                });

                var $cookies;

                angular.injector(['ngCookies'])
                    .invoke([
                        '$cookies',
                        function ($cookiestemp) {
                            $cookies = $cookiestemp;
                        }
                    ]);

                $httpProvider.defaults.headers.common['Accept-Language'] = $cookies['language'];
                $httpProvider.defaults.headers.common['Access-Control-Allow-Origin'] = true;
            }
        ]);
})();

(function () {
    'use strict';

    angular.module('oneKeyApp.placeMigration', [
            'ngCookies', 'ngSanitize', 'ngFileUpload', 'ngAnimate'
        ])
        .config(['$httpProvider', function ($httpProvider) {
                if (localStorage.getItem('access_token')) {
                    $httpProvider.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('access_token');
                }

                $httpProvider.interceptors.push(function ($q) {
                    return {
                        responseError: function (response) {
                            return $q.reject(response);
                        }
                    };
                });

                var $cookies;

                angular.injector(['ngCookies'])
                    .invoke([
                        '$cookies',
                        function ($cookiestemp) {
                            $cookies = $cookiestemp;
                        }
                    ]);

                $httpProvider.defaults.headers.common['Accept-Language'] = $cookies['language'];
                $httpProvider.defaults.headers.common['Access-Control-Allow-Origin'] = true;
            }
        ]);
})();

(function(module) {
    'use strict';

    module.factory('bulkInventoryService', bulkInventoryService);

    function bulkInventoryService($http, urls, $q, inventoryGridConfig) {
        return {
            update: update,
            refreshInventoryGrid: refreshInventoryGrid
        };

        function update(request) {
            var url = urls('baseApiUrl').concat('/accounts/me/bulk/update'), 
                deferred = $q.defer();

            $http.post(url, request)
                .success(deferred.resolve)
                .error(deferred.reject);

            return deferred.promise;
        }

        function refreshInventoryGrid() {
            inventoryGridConfig.allItemsSelected = false;
            inventoryGridConfig.selectAll();
        }
    }

    bulkInventoryService.$inject = ['$http', 'urls', '$q', 'inventoryGridConfig'];

}(angular.module('oneKeyApp')));
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('cssify', function () {
        return function (value) {
            return String(value).replace('/', '');

        };
    });
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('dates', ['$filter', 'language', function ($filter, language) {
        return {
            cookies: function () {
                var $cookies;
                angular.injector(['ngCookies']).invoke(['$cookies', function ($cookiestemp) {
                    $cookies = $cookiestemp;
                }]);
                return $cookies;
            },
            date: function (isDisplay) {
                var $cookies = this.cookies();

                var format = isDisplay ? "dd/MM/yyyy" : "DD/MM/YYYY";
                if ($cookies.language === "en-US") {
                    format = isDisplay ? "MM/dd/yyyy" : "MM/DD/YYYY";
                }

                if ($cookies.language != undefined) {
                    if ($cookies.language === "pl-PL"
                        || $cookies.language === "sv-SE") {
                        format = isDisplay ? "yyyy/MM/dd" : "YYYY/MM/DD";
                    }

                    if ($cookies.language.match(/^hu-HU|lt-LT$/)) {
                        format = isDisplay ? "yyyy/MM/dd" : "YYYY/MM/DD";
					}

					if ($cookies.language === "fr-ca" || $cookies.language === "fr-CA") {
						format = isDisplay ? "yyyy/MM/dd" : "YYYY/MM/DD";
					}
                }

                return format;
            },
            longDateFormat: 'MMMM d, yyyy',
            longDateTimeFormat: 'MMMM d, yyyy h:mm a',
            shortDateTimeFormat: 'MMM d, yyyy h:mm a',
            dateTime: function (isDisplay) {
                var dateFormat = this.date(isDisplay);
                return dateFormat + ' - H:mm:ss';
            },
            shortDateTime: function (isDisplay) {
                var dateFormat = this.date(isDisplay);
                return dateFormat + ' h:mm a';
            },
            shortTime: 'h:mm a',
            momentUtcToLocal: function (utcDate) {
                var $cookies = this.cookies();
                var currentLocale = $cookies.language.toLowerCase();
                
                if (utcDate.indexOf('Z') === -1 && utcDate.indexOf('+') === -1) {
                    utcDate += 'Z';
                }
                moment.locale(currentLocale);
                return moment(utcDate).format('l');
                
            },
            convertUtcToLocal: function (utcDate, format) {
                if (!utcDate) {
                    return;
                }

                if (utcDate.indexOf('Z') === -1 && utcDate.indexOf('+') === -1) {
                    utcDate += 'Z';
                }

                if (!format) {
                    format = this.shortDateTime(true);
                }

                return $filter('date')(utcDate, format);
            },
            api: 'YYYY-MM-DDThh:mm:ss.SSSZ',
            getDatePickerOptions: function (verticalAlign) {
                if (verticalAlign == undefined) {
                    verticalAlign = 'bottom';
                }
                var format = this.date(false);
				var localeByDomain = language.getLocale();
                return {
                    format: format,
                    debug: false,
                    widgetPositioning: { horizontal: 'left', vertical: verticalAlign },
                    locale: localeByDomain
                };
            },
            convertLocalToUtc: function (date) {
                return date.length > 0 ? moment(date, this.date(false)).format(this.api) : undefined;
            },

            getLanguageCookies: function () {
                var $cookies = this.cookies();
                var currentLocale = $cookies.language.toLowerCase();
                return currentLocale;
            }
        }
    }]);
}());

(function(module) {
    'use strict';

    module.factory('featureToggle', featureToggle);

    function featureToggle($http, urls, $q) {
        return {
            getAll: getAll
        };  

        function getAll() {
            var url = urls('baseApiUrl').concat('/config/features?platform=');
            var deferred = $q.defer();
            $http.get(url)
                .success(deferred.resolve)
                .error(deferred.reject);

            return deferred.promise;
        }
    }

    featureToggle.$inject = ['$http', 'urls', '$q'];

}(angular.module('oneKeyApp')));
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('focus', ['$rootScope', '$timeout', function ($rootScope, $timeout) {
        return function (name) {
            $timeout(function () {
                $rootScope.$broadcast('metFocusOn', name);
            });
        };
    }]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('inventoryFilters', ['$filter', '$rootScope', 'localize', function ($filter, $rootScope, metLocalize) {
        var service = {};
        service.filters = [];
        service.availableFilters = { locationIds: [], manufacturerIds: [], personIds: [], tradeIds: [], statusIds: [], categoryIds: [] };
        service.selectedFilters = [];
        service.oneKeyOnly = false;
        service.tickOnly = false;
        service.searchRequest = {};
        service.hasChanges = false;
        service.searchTerm = "";
        service.selectedFilterCount = 0;
        service.messages = {
            missing: metLocalize('fieldNames', 'itemStatus_Missing')
        }

        service.filtersForTransfersDashboard = {placeIds: [], personIds: [], divisionIds: []}; 

        if (localStorage.getItem("selectedFilters")) {
            service.selectedFilters = JSON.parse(localStorage.getItem("selectedFilters"));
        }

        service.createFilters = function (itemFieldFactory) {
            service.filters.push(createFilter("place", "placeId", "list", itemFieldFactory.locations, service.availableFilters.placeIds, 'placeName', 'placeId'));
            service.filters.push(createFilter("lastSeen", "lastSeen", "date"));
            service.filters.push(createFilter("manufacturer", "manufacturerId", "list", itemFieldFactory.manufacturers, service.availableFilters.manufacturerIds, 'manufacturerName', 'manufacturerId'));
            service.filters.push(createFilter("person", "PersonId", "list", itemFieldFactory.people, service.availableFilters.personIds, 'personName', 'personId'));
            service.filters.push(createFilter("division", "divisionId", "list", itemFieldFactory.trades, service.availableFilters.tradeIds, 'divisionName', 'divisionId'));
            service.filters.push(createFilter("maintenance", "maintenanceNeeded", "bool"));
            service.filters.push(createFilter("status", "itemStatus", "list", itemFieldFactory.statuses, service.availableFilters.statusIds, "statusName", "statusId"));
            service.filters.push(createFilter("price", "price", "list", itemFieldFactory.values, [1, 2, 3, 4, 5], 'label', 'id'));
            service.filters.push(createFilter("purchaseDate", "datePurchased", "date"));
            service.filters.push(createFilter("unseen", "daysUnseen", "date"));
            service.filters.push(createFilter("upcomingService", "upcomingService", "date"));
            service.filters.push(createFilter("pastDueService", "pastDueService", "bool"));
            service.filters.push(createFilter("outsideGeofence", "outsideGeofence", "bool"));
            service.filters.push(createFilter("category", "category", "list", itemFieldFactory.parentCategories, service.availableFilters.categoryIds, 'categoryName', 'categoryId'));
        }        

        $rootScope.$on("list-updated", function (event, args) {
            var filter = findFilter(args.name);
            if (filter) {
                    filter.items = args.items;
            }
        });
        
        function createFilter(name, labelName, filterType, items, enabledItems, itemLabelProperty, itemIdProperty, index) {
            return {
                name: name,
                label: labelName,
                filterType: filterType,
                items: items,
                enabledItems: enabledItems,
                itemLabelProperty: itemLabelProperty,
                itemIdProperty: itemIdProperty
            };
        }

        service.closeAllFilters = function () {
            _.forEach(service.filters, function (value) {
                value.isOpened = false;
            });
        }


        service.updateAvailableFilters = function(filtersAvailable) {
            service.availableFilters = filtersAvailable;
            setEnabledItems("place", service.availableFilters.placeIds);
            setEnabledItems("manufacturer", service.availableFilters.manufacturerIds);
            setEnabledItems("person", service.availableFilters.personIds);
            setEnabledItems("division", service.availableFilters.tradeIds);
            setEnabledItems("status", service.availableFilters.statusIds);
            setEnabledItems("category", service.availableFilters.categoryIds);
        }

        function setEnabledItems(filterName, enabledItems) {
            var filter = findFilter(filterName);
            if (filter) {
                filter.enabledItems = enabledItems
            }
        }

        function findFilter(filterName) {
            return $filter('filter')(service.filters, { name: filterName })[0];
        }

        service.nukeFilters = function() {
            localStorage.removeItem('selectedFilters');
            localStorage.removeItem('oneKeyOnly');
            localStorage.removeItem('transferFrom');
            localStorage.removeItem('tickOnly');
        }

        service.addSelectedFilter = function (filterName, id, label, isQuickFilter, value) {
            service.hasChanges = true;
            var selectedFilter = findSelectedFilter(id, filterName);
            var newFilter = { id: id, label: label, filterName: filterName, isSaved: false, isSelected: true, isQuickFilter: isQuickFilter, value: value };
            if (selectedFilter) {
                var filterToRemove = $filter('filter')(filtersToRemove, { id: selectedFilter.id, filterName: selectedFilter.filterName })[0];
                var filterIndex = filtersToRemove.indexOf(filterToRemove);
                if (filterIndex >= 0) {
                    filtersToRemove.splice(filterIndex, 1);
                }
            } else {
                service.selectedFilters.push(newFilter);
                service.selectedFilterCount += 1;
            }
        }
        
        var filtersToRemove = [];
        service.removeSelectedFilter = function (filterName, id) {
            var selectedFilter = findSelectedFilter(id, filterName);
            if (selectedFilter) {
                service.hasChanges = true;
                filtersToRemove.push(selectedFilter);
                service.selectedFilterCount -= 1;
            }
        }

        function findSelectedFilter(id, filterName) {
            return $filter('filter')(service.selectedFilters, { id: id, filterName: filterName })[0];
        }

        service.removeAllFilters = function () {
            var selected = service.selectedFilters.slice();
            _.forEach(selected, function (element) {
                service.quickRemoveFilter(element);
            });

            // Uncheck the quick filters
            var quickFilters = document.getElementsByClassName('quick-filter');
            _.forEach(quickFilters, function (filter) {
                    filter.children[0].checked = false;
            });

            // Make sure the marked missing side nav goes away as well
            // since we mark that if quick filter for marked missing is checked.
            var sideNavElement = document.getElementById(service.messages.missing.value);
            if (sideNavElement !== null) {
                sideNavElement.checked = false;
            }
            service.selectedFilterCount = 0;
        }

        service.hasFilters = function () {
            return service.selectedFilters.length > 0;
        }

        service.quickRemoveFilter = function (selectedFilter) {
            var filterIndex = service.selectedFilters.indexOf(selectedFilter);
            service.selectedFilters.splice(filterIndex, 1);
            localStorage.removeItem("maintenance");

            switch (selectedFilter.filterName) {
                case "oneKeyOnly": 
                    service.oneKeyOnly = false;
                    break;
                case "tickOnly":                    
                    service.tickOnly = false;
                    break;
                default:
                    clearFilter(selectedFilter.filterName, selectedFilter.id);
                    break;
            }
            localStorage.setItem("selectedFilters", JSON.stringify(service.selectedFilters));
            localStorage.setItem("oneKeyOnly", service.oneKeyOnly);
            localStorage.setItem("tickOnly", service.tickOnly);
        }

        function clearFilter(filterName, id) {
            var filter = findFilter(filterName);
            switch (filter.filterType) {
                case "list":
                    _.forEach(filter.items, function (value, index) {
                        if (value[filter.itemIdProperty] === id) {
                            value.isSelected = false;
                        }
                    });
                    break;
                case "date":
                    filter.value = undefined;
                    break;
                case "bool":
                    filter.value = undefined;
                    break;
            }
        }

        var oneKey = localStorage.getItem("oneKeyOnly");
        if (oneKey) { service.oneKeyOnly = oneKey; }

        var tick = localStorage.getItem("tickOnly");
        if (tick) { service.tickOnly = tick; }

        service.updateFilterResults = function () {
            _.forEach(filtersToRemove, function (value) {
                var filterIndex = service.selectedFilters.indexOf(value);
                service.selectedFilters.splice(filterIndex, 1);
            });
            localStorage.setItem("selectedFilters", JSON.stringify(service.selectedFilters));
            filtersToRemove = [];

            _.forEach(service.selectedFilters, function (value) {
                value.isSaved = true;
            });

            service.searchRequest.searchTerm = service.searchTerm;
            service.searchRequest.oneKeyOnly = service.oneKeyOnly;
            service.searchRequest.tickOnly = service.tickOnly;
            service.searchRequest.places = getSelectedIds("place");
            service.searchRequest.manufacturers = getSelectedIds("manufacturer");
            service.searchRequest.people = getSelectedIds("person");
            service.searchRequest.divisions = getSelectedIds("division");
            service.searchRequest.itemStatuses = getSelectedIds("status");
            service.searchRequest.priceRanges = getSelectedIds('price');
            service.searchRequest.daysSinceLastSeen = getFilterValue('lastSeen');
            service.searchRequest.daysSincePurchaseDate = getFilterValue('purchaseDate');
            service.searchRequest.maintanenceNeeded = getFilterValue('maintenance');
            service.searchRequest.daysUnseen = getFilterValue('unseen');
            service.searchRequest.pastDueService = getFilterValue('pastDueService');
            service.searchRequest.outsideGeofence = getFilterValue('outsideGeofence');
            service.searchRequest.daysTillUpcomingService = getFilterValue('upcomingService');
            service.searchRequest.categories = getSelectedIds("category");
            service.hasChanges = false;
            localStorage.setItem("oneKeyOnly", service.searchRequest.oneKeyOnly);
            localStorage.setItem("tickOnly", service.searchRequest.tickOnly);

            service.filtersForTransfersDashboard.placeIds = service.searchRequest.places;
            service.filtersForTransfersDashboard.personIds = service.searchRequest.people;
            service.filtersForTransfersDashboard.divisionIds = service.searchRequest.divisions;

            $rootScope.$broadcast('updated-Results', service.filtersForTransfersDashboard);
        }

        function getSelectedIds(filterName) {
            var filter = findFilter(filterName);
            var items = [];
            var filteredItems = [];
            var selectedFilters = JSON.parse(localStorage.getItem("selectedFilters"));

            if (filter) {
                items = $filter('filter')(filter.items, { isSelected: true }).map(function (e) { return e[filter.itemIdProperty] });
            }
            
            if (items.length === 0) {
                filteredItems = $filter('filter')(selectedFilters, { isSelected: true, filterName: filterName }).map(function (e) { return e['id'] });
                if (filteredItems.length > 0)
                    return filteredItems;
            }

            return items;
        }

        function getFilterValue(filterName) {
            var filter = findFilter(filterName);
            var selectedFilters = JSON.parse(localStorage.getItem("selectedFilters"));

            var filterItem = selectedFilters.filter(function (item) {
                return item.filterName === filterName;
            })

            if (filterItem.length > 0) {
                return filterItem[0].value;
            }

            if (localStorage.getItem("maintenance") && localStorage.getItem("maintenance") !== "undefined") {
                filter.value = localStorage.getItem("maintenance");
            }
            return filter ? filter.value : undefined;
        }

        return service;
    }]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('inventoryGridConfig', ['$filter', '$rootScope', 'localize', 'metLocalStorage', 'featureToggle',
    function ($filter, $rootScope, metLocalize, metLocalStorage, featureToggle) {
        var service = {};

        service.loadedGroups = [];
        service.gridSort = metLocalStorage.getGridSort();
        service.allItemsSelected = false;
        service.totalResults = 0;
        service.resultsPerPage = metLocalStorage.getResultsPerPage();
        service.pageIndex = 0;
        service.groupBy = 0;
        service.availableFilters = [];

        var messages = {
            available: metLocalize('fieldNames', 'itemStatus_Available'),
            damaged: metLocalize('fieldNames', 'itemStatus_Damaged'),
            missing: metLocalize('fieldNames', 'itemStatus_Missing'),
            retired: metLocalize('fieldNames', 'itemStatus_Retired'),
        }

        service.gridUpdated = function (response, isPaging) {
            service.loadedGroups.splice(0, service.loadedGroups.length);
            _.forEach(response.groupedItems, function (group, index) {
                service.loadedGroups.push(group);
                group.selected = service.allItemsSelected || service.selectedGroupIds.indexOf(group.id) != -1;
                service.allItemsSelected = true;
                _.forEach(group.items, function (item, index) {
                    item.selected = service.selectedItemIds.indexOf(item.id) != -1;
                    if (!item.selected) {
                        service.allItemsSelected = false;
                        group.selected = false;
                    }

                    switch (item.statusId) {
                        case 0:
                            item.status = messages.available.value;
                            break;
                        case 1:
                            item.status = messages.missing.value;
                            break;
                        case 2:
                            item.status = messages.damaged.value;
                            break;
                        case 3:
                            item.status = messages.retired.value;
                            break;
                    }
                });
            });
            service.totalResults = response.totalCount;
            service.availableFilters = response.availableFilters;
            var startNumber = service.getSkipTotal() + 1;
            var pageNumber = service.pageIndex + 1;
            $rootScope.$broadcast("grid-updated", { isPaging: isPaging, totalResults: service.totalResults, startNumber: startNumber, currentPage: pageNumber, resultsPerPage: service.resultsPerPage, availableFilters: service.availableFilters });
        }

        service.bulkUpdateGridProperties = function (itemProperty, value) {
            _.forEach(service.loadedGroups, function (group, index) {
                _.forEach(group.items, function (item, index) {
                    if (item.selected) {
                        item[itemProperty] = value;
                    }
                });
            });
        }

        service.selectedGroupIds = [];
        service.selectedItemIds = [];
        service.selectedLocationIds = [];
        function addIdToList(list, id) {
            var listIndex = list.indexOf(id);
            if (listIndex == -1) {
                list.push(id);
            }            
        }

        function removeIdFromList(list, id) {
            var listIndex = list.indexOf(id);
            if (listIndex > -1) {
                list.splice(listIndex, 1);
            }            
        }

        service.selectedFieldCount = 0;
        service.selectedGroupIds = [];
        service.updateSelectedFields = function () {
            service.selectedFieldCount = 0;
                _.forEach(service.loadedGroups, function (group, index) {
                    var count = 0;
                    if (group.selected) {
                        count = group.count;
                        addIdToList(service.selectedGroupIds, group.id);
                        _.forEach(group.items, function (item, index) {
                            if (item.selected) {
                                addIdToList(service.selectedItemIds, item.id);
                            }
                        })
                    } else {
                        removeIdFromList(service.selectedGroupIds, group.id);
                        _.forEach(group.items, function (item, index) {
                            if (item.selected) {
                                count++;
                                addIdToList(service.selectedItemIds, item.id);
                                addIdToList(service.selectedLocationIds, item.id + "|" + item.placeId);
                            } else {
                                removeIdFromList(service.selectedItemIds, item.id);
                                removeIdFromList(service.selectedLocationIds, item.id + "|" + item.placeId);
                            }
                        });
                    }
                    service.selectedFieldCount += count;
                });
                service.selectedFieldCount = service.selectedItemIds.length;
        }

        service.selectAll = function () {
            _.forEach(service.loadedGroups, function (group, index) {
                group.selected = service.allItemsSelected;
                _.forEach(group.items, function (item, index) {
                    item.selected = service.allItemsSelected;
                    addIdToList(service.selectedItemIds, item.id);
                    addIdToList(service.selectedLocationIds, item.id + "|" + item.placeId);
                });
            });
            service.updateSelectedFields();
        }

        service.setResultsPerPage = function(results) {
            metLocalStorage.setResultsPerPage(results);
            service.resultsPerPage = results;
        }

        service.headerValues = [
            createHeaderValue("inventoryToolNumber", "toolNumber", "small", true),
            createHeaderValue("inventoryGridModelDescription", "description", "large", true),
            createHeaderValue("serialNumber", "serialNumber", "large", true),
            createHeaderValue("barcodeId", "barcodeId", 'medium', false),
            createHeaderValue("manufacturerId", "manufacturer", "medium", false),
            createHeaderValue("categoryId", "category", "medium", true),
            createHeaderValue("placeId", "place", "small", true),
            createHeaderValue("personId", "person", "small", true),
            createHeaderValue("divisionId", "trade", "small", false),
            createHeaderValue("itemStatus", "status", "small", false),
            createHeaderValue("lastSeen", "lastSeen", "medium", true),
            createHeaderValue("coinCellLevel", "coinCell", "large", false),
            createHeaderValue("price", "price", "small", false),
            createHeaderValue("datePurchased", "purchaseDate", "medium", false),
            createHeaderValue("purchaseLocation", "purchaseLocation", "large", false),
        ];

        featureToggle.getAll()
            .then(function (response) {
                service.enableBarcode = response.inventorybarcode;
                if (!service.enableBarcode) {
                    service.headerValues.splice(3, 1);
                }
            });

        service.columnIsVisible = function (columnName) {
            var column = $filter('filter')(service.headerValues, { columnName: columnName })[0];
            return column ? column.isVisible : false;
        }

        service.getSkipTotal = function () {
            return service.resultsPerPage * service.pageIndex;
        }

        function createHeaderValue(labelValue, columnName, width, visible) {
            var isSorted = service.gridSort.field == columnName;
            var isDescending = isSorted && service.gridSort.isDescending;
            var hasIcon = columnName == "description";
            var columnInfo = metLocalStorage.getColumnInfo(columnName, visible);
            var header = {
                label: metLocalize('fieldNames', labelValue), columnName: columnName, isVisible: columnInfo.visible,
                isSorted: isSorted, sortDescending: isDescending, hasIcon: hasIcon
            };

            switch (width) {
                case "large":
                    header.isLarge = true;
                    break;
                case "medium":
                    header.isMedium = true;
                    break;
                default:
                    header.isSmall = true;
                    break;
            }

            return header;
        }

        return service;
    }]);
}());

(function () {
	'use strict';

	var oneKeyApp = angular.module('oneKeyApp');

	oneKeyApp.service('language', ['$filter', function ($filter) {
		const MEXICAN_SPANISH = 'es-MX';
		const FRENCH_CANADIAN = 'fr-CA';
		const CANADIAN_ENGLISH = 'en-CA';
		const US_ENGLISH = 'en-US';

		var $cookies;
		var locale;

		angular.injector(['ngCookies']).invoke(['$cookies', function ($cookiestemp) {
			$cookies = $cookiestemp;
		}]);

		return {
			getLocale: function () {
				var cookieLanguage = $cookies.language;
				var hostSegments = window.location.host.split('.');
				var domain = _.last(hostSegments);

				switch (domain) {
					case 'eu':
						return cookieLanguage;
					case 'mx':
						return MEXICAN_SPANISH;
					case 'ca':
						return cookieLanguage == FRENCH_CANADIAN ? FRENCH_CANADIAN : CANADIAN_ENGLISH;
					default:
						return US_ENGLISH;
				}
			}
		}
	}]);
}());
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('localize', ['$http', '$q', 'urls', function ($http, $q, metUrls) {
        var httpPromise = $http.get(metUrls('metaStrings'));

        return function (group, name) {
            var responsePromise = $q.defer();
            var result = {
                promise: responsePromise.promise
            };
            httpPromise.then(function (results) {
                var strings = results.data;
                if (!angular.isDefined(strings[group])) {
                    throw new Error("Localization group is not defined: " + group);
                }
                name = name.toLowerCase();
                var match = _.find(strings[group], function (item) {
                    return item.key.toLowerCase() == name;
                });
                if (!angular.isDefined(match)) {
                    throw new Error("Localization string is not defined: " + name);
                }
                result.value = match.value;
                responsePromise.resolve(match.value);
            });

            return result;
        }
    }]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('metLocalStorage', ['$window', function ($window) {
        var _version = 1.01;

        var get = function (variableName) {
            return JSON.parse(localStorage.getItem(variableName));
        }

        var set = function (variableName, obj) {
            localStorage.setItem(variableName, JSON.stringify(obj));
        }

        return {
            getColumnInfo: function (columnName, visibleDefault) {
                var column = get('selectedColumns_v1.3_' + columnName);

                if (!column || column == null) {
                    column = { visible: visibleDefault };
                    this.setColumnInfo(columnName, column);
                }

                return column;
            },
            setColumnInfo: function (columnName, columnObj) {
                set('selectedColumns_v1.3_' + columnName, columnObj);
            },

            getGridSort: function () {
                var sort = get('gridSort_v2.0');
                if (!sort) {
                    sort = { field: 'toolNumber', isDescending: false }
                }
                return sort;
            },
            setGridSort: function (sort) {
                set('gridSort_v2.0', sort);
            },

            //getColumnOrder: function () {
            //    var columnOrder = get("gridColumnOrder_v1.2");
            //    if (!columnOrder || columnOrder == null) {
            //        columnOrder = ["id", 'toolNumber', 'description', 'category', 'location', 'trade', 'model', 'manufacturer',
            //                        'serialNumber', 'price', 'status', 'purchaseLocation', 'person', 'lastSeen'];
            //    }
            //    return columnOrder;
            //},
            //setColumnOrder: function (columnOrder) {
            //    set("gridColumnOrder_v1.2", columnOrder);
            //},

            getResultsPerPage: function () {
                var resultsPerPage = get('resultsPerPage');
                if (!resultsPerPage) {
                    resultsPerPage = 10;
                }

                var userAgent = $window.navigator.userAgent;

                var browsers = { chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i };
                var notIe = false;
                for (var key in browsers) {
                    if (browsers[key].test(userAgent)) {
                        notIe = true;
                    }
                };

                if (notIe && resultsPerPage > 200) {
                    resultsPerPage = 10;
                } else if (!notIe && resultsPerPage > 50) {
                    resultsPerPage = 10;
                }

                return resultsPerPage;
            },
            setResultsPerPage: function (resultsPerPage) {
                set('resultsPerPage', resultsPerPage);
            }
        };
    }]);
}());

(function () {
    'use strict';

    var app = angular.module('oneKeyApp');

    var _width = null;
    var onekey = jQuery214('#onekey');
    if (onekey.length > 0) {
        _width = (onekey.width() / 2);
    }

    var notify = {
        success: 'success',
        info: 'info',
        warning: 'warning',
        error: 'error'
    }

    var _icon = {
        'success': 'alert-success',
        'info': 'alert-info',
        'warning': 'alert-warning',
        'error': 'alert-danger',
    };

    app.service('notify', function () {
        toastr.options = {
            'positionClass': 'toast-top-center',
            'toastClass': 'alert',
            'iconClasses': {
                error: _icon[notify.error],
                info: _icon[notify.info],
                success: _icon[notify.success],
                warning: _icon[notify.warning]
            },
            'target': '#onekey'
        };

        /* Assumes 'positionClass' is being set to 'toast-top-center'. 
           Reason: this halves the toast message and centers it at the mid point of the target, #onekey.
           align method uses this knowledge and offsets accordingly (moving the midpoint to the right) */
        function align(toast) {
            if (toast) {
                if (_width != null) {
                    var width = _width - (toast.width() / 2);
                    toast.css('left', width + 'px');
                }
            }
            return toast;
        }

        /* Determines if the message for a given type already exists. 
           Any issues, returns false. */
        function exists(type, message) {
            try {
                var toasts = $('#toast-container .alert.' + _icon[type] + ' .toast-message');

                if (toasts.length == 0) {
                    return false;
                }

                var lower = message.toLowerCase();
                return _.any(toasts, function (item) {
                    return lower === item.innerHTML.toLowerCase();
                });
            } catch(error) { }

            return false;
        }

        return {
            success: function (message, override) {
                this.notify(notify.success, message, override);
            },
            info: function (message, override) {
                this.notify(notify.info, message, override);
            },
            warning: function (message, override) {
                this.notify(notify.warning, message, override);
            },
            error: function (message, override) {
                this.notify(notify.error, message, override);
            },
            itemAdded: function(message) {
                toastr.options = {
                    "closeButton": false,
                    "debug": false,
                    "newestOnTop": false,
                    "progressBar": false,
                    "positionClass": "toast-top-center",
                    "preventDuplicates": false,
                    "onclick": null,
                    "showDuration": "300",
                    "hideDuration": "1000",
                    "timeOut": "3500",
                    "extendedTimeOut": "1000",
                    "showEasing": "swing",
                    "hideEasing": "linear",
                    "showMethod": "fadeIn",
                    "hideMethod": "fadeOut"
                }
                toastr['success'](message);
            },
            notify: function (type, message, override) {
                override = typeof override !== 'undefined' ? override : {};

                if (!override.repeatable) {
                    if (exists(type, message)) {
                        return;
                    }
                }

                var toast = null;
                switch (type) {
                    case notify.success:
                        toast = toastr.success(message, null, override);
                        break;
                    case notify.warning:
                        toast = toastr.warning(message, null, override);
                        break;
                    case notify.error:
                        toast = toastr.error(message, null, override);
                        break;
                    default:
                        toast = toastr.info(message, null, override);
                        break;
                };

                align(toast);
            }
        };
    });
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('pageVars', ['$window', function ($window) {
        return {
            get: function (variable) {
                if (!$window.met || !$window.met[variable]) {
                    throw new Error('Missing page variable: $window.met.' + variable);
                }
                return $window.met[variable];
            }
        };
    }]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('sort', function () {
        var sortDirection = false;
        var sortOrder = null;

        return {
            by: by,
            isSortedBy: isSortedBy,
            sortOrder: sortOrder,
            sortDirection: sortDirection,
            getThSortClass: getThSortClass,
            getSortDirectionClass: getSortDirectionClass
        };

        function by(order, $event) {
            if (this.isSortedBy(order)) {
                this.sortDirection = !this.sortDirection;
            } else {
                this.sortDirection = false;
            }
            this.sortOrder = order;
            $event.preventDefault();
        };

        function isSortedBy(order) {
            var expectedOrder = order;
            if (order instanceof Array) {
                expectedOrder = order[0];
            }
            var actualSortOrder = this.sortOrder;
            if (this.sortOrder instanceof Array) {
                actualSortOrder = this.sortOrder[0];
            }
            return expectedOrder === actualSortOrder;
        };

        function getSortDirectionClass() {
            if (this.sortDirection) {
                return "icon icon-chevron-down";
            }
            return "icon icon-chevron-up";
        };

        function getThSortClass(order) {
            if (this.isSortedBy(order)) {
                if (this.sortDirection) {
                    return "desc";
                }
                return "asc";
            }
            return "";
        };


    });
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('urls', [
        'pageVars', function (metPageVars) {
            var allUrls = metPageVars.get('urls');

            return function (name) {
                if (!angular.isDefined(allUrls[name])) {
                    throw new Error('Url is not configured: ' + name); // TODO: Localize
                }
                return allUrls[name];
            }
        }
    ]);

    function configSettings() {
        return {
            getSettings: function (variable) {
                if (!window.settings || !window.settings[variable]) {

                    throw new Error('Missing page variable: window.settings.' + variable);
                }
                return window.settings[variable];
            },
            get: function () {
                var allSettings = this.getSettings('appSettings');
                return function (name) {
                    if (!angular.isDefined(allSettings[name])) {
                        throw new Error('App Setting Is Not Configured: ' + name);
                    }
                    return allSettings[name];
                }
            }
        }
    }

    oneKeyApp.service('configSettings', configSettings);
}());

(function(module){
    'use strict';

    module.factory('userService', userService);
    userService.$inject = ['$http', '$q', 'urls'];

    function userService($http, $q, urls){
        function setupUser(token){
            var deferred = $q.defer();
            var url = urls('setupUser');

            if(typeof(token) === 'undefined'){
                return deferred.promise;
            }
            var config = {
                headers: {
                    'Authorization': 'Bearer ' + token
                }
            };
            $http.post(url, null, config)
                .success(deferred.resolve)
                .error(deferred.reject);

            return deferred.promise;
        }

        return {
            setupUser: setupUser
        };
    }

}(angular.module('oneKeyApp')));
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('validate', function () {
        return {
            compareStrings: compareStrings
        }

        function compareStrings(string1, string2, ignoreCase, useLocale) {
            if (string1.length < 1) {
                string1 = '';
            }
            if (string2.length < 1) {
                string2 = '';
            }
            if (ignoreCase) {
                if (useLocale) {
                    string1 = string1.toLocaleLowerCase();
                    string2 = string2.toLocaleLowerCase();
                }
                else {
                    string1 = string1.toLowerCase();
                    string2 = string2.toLowerCase();
                }
            }
            return string1 === string2;
        }
    });
}());
/**
 * Placeholder for non-HTML5 browsers ... specifically IE8 and IE9, but also
 * works with Firefox 3 and possibly others.
 *
 * Always toggles on/off the placeholder class (default is "placeholder").
 * Shims in the visual effects for older IE.
 *
 * Quick Usage:
 *
 *     <input ng-model="xyz" placeholder="Enter Value" />
 *
 *     <textarea ng-model="xyz" placeholder="Enter Value"
 *         placeholder-class="placeholder"></textarea>
 *
 * Styling:
 *
 * Browsers still use specific placeholder selectors.  IE8 and 9 can now style
 * the text with a `placeholder` class.
 *
 *     .placeholder { color: red; }
 *
 * @link https://github.com/tests-always-included/angular-placeholder
 * @license MIT
 */


/*global angular*/
(function (undef) {
    "use strict";

    var propName, needsShimByNodeName;

    propName = 'placeholder';
    needsShimByNodeName = {};

    angular.module("taiPlaceholder", []).directive("placeholder", [
        "$document",
        function ($document) {
            // Determine if we need to perform the visual shimming
            angular.forEach(['INPUT', 'TEXTAREA'], function (val) {
                needsShimByNodeName[val] = $document[0].createElement(val)[propName] === undef;
            });

            /**
             * Determine if a given type (string) is a password field
             *
             * @param {string} type
             * @return {boolean}
             */
            function isPasswordType(type) {
                return type && type.toLowerCase() === "password";
            }

            return {
                require: "ngModel",
                restrict: "A",
                link: function ($scope, $element, $attributes, $controller) {
                    var className, currentValue, text;

                    text = $attributes[propName];
                    className = $attributes[propName + "Class"] || propName;

                    // This does the class toggling depending on if there
                    // is a value or not.
                    $scope.$watch($attributes.ngModel, function (newVal) {
                        currentValue = newVal || "";

                        if (!currentValue) {
                            $element.addClass(className);
                        } else {
                            $element.removeClass(className);
                        }
                    });

                    if (needsShimByNodeName[$element[0].nodeName]) {
                        // These bound events handle user interaction
                        $element.bind("focus", function () {
                            if (currentValue === "") {
                                // Remove placeholder text
                                $element.val("");
                            }
                        });
                        $element.bind("blur", function () {
                            if ($element.val() === "") {
                                // Add placeholder text
                                $element.val(text);
                            }
                        });

                        // This determines if we show placeholder text or not
                        // when there was a change detected on scope.
                        $controller.$formatters.unshift(function (val) {
                            /* Do nothing on password fields, as they would
                             * be filled with asterisks.  Issue #2.
                             */
                            if (isPasswordType($element.prop("type"))) {
                                return val;
                            }

                            // Show placeholder text instead of empty value
                            return val || text;
                        });
                    }
                }
            };
        }
    ]);
}());
if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.exports === exports){
  module.exports = 'highcharts-ng';
}
(function () {
  'use strict';
  /*global angular: false, Highcharts: false */

  angular.module('highcharts-ng', [])
    .factory('highchartsNGUtils', highchartsNGUtils)
    .directive('highchart', ['highchartsNGUtils', '$timeout', highchart]);

  function highchartsNGUtils() {

    return {

      //IE8 support
      indexOf: function (arr, find, i /*opt*/) {
        if (i === undefined) i = 0;
        if (i < 0) i += arr.length;
        if (i < 0) i = 0;
        for (var n = arr.length; i < n; i++)
          if (i in arr && arr[i] === find)
            return i;
        return -1;
      },

      prependMethod: function (obj, method, func) {
        var original = obj[method];
        obj[method] = function () {
          var args = Array.prototype.slice.call(arguments);
          func.apply(this, args);
          if (original) {
            return original.apply(this, args);
          } else {
            return;
          }

        };
      },

      deepExtend: function deepExtend(destination, source) {
        //Slightly strange behaviour in edge cases (e.g. passing in non objects)
        //But does the job for current use cases.
        if (angular.isArray(source)) {
          destination = angular.isArray(destination) ? destination : [];
          for (var i = 0; i < source.length; i++) {
            destination[i] = deepExtend(destination[i] || {}, source[i]);
          }
        } else if (angular.isObject(source)) {
          for (var property in source) {
            destination[property] = deepExtend(destination[property] || {}, source[property]);
          }
        } else {
          destination = source;
        }
        return destination;
      }
    };
  }

  function highchart(highchartsNGUtils, $timeout) {

    // acceptable shared state
    var seriesId = 0;
    var ensureIds = function (series) {
      var changed = false;
      angular.forEach(series, function(s) {
        if (!angular.isDefined(s.id)) {
          s.id = 'series-' + seriesId++;
          changed = true;
        }
      });
      return changed;
    };

    // immutable
    var axisNames = [ 'xAxis', 'yAxis' ];
    var chartTypeMap = {
      'stock': 'StockChart',
      'map':   'Map',
      'chart': 'Chart'
    };

    var getMergedOptions = function (scope, element, config) {
      var mergedOptions = {};

      var defaultOptions = {
        chart: {
          events: {}
        },
        title: {},
        subtitle: {},
        series: [],
        credits: {},
        plotOptions: {},
        navigator: {enabled: false}
      };

      if (config.options) {
        mergedOptions = highchartsNGUtils.deepExtend(defaultOptions, config.options);
      } else {
        mergedOptions = defaultOptions;
      }
      mergedOptions.chart.renderTo = element[0];

      angular.forEach(axisNames, function(axisName) {
        if(angular.isDefined(config[axisName])) {
          mergedOptions[axisName] = angular.copy(config[axisName]);

          if(angular.isDefined(config[axisName].currentMin) ||
              angular.isDefined(config[axisName].currentMax)) {

            highchartsNGUtils.prependMethod(mergedOptions.chart.events, 'selection', function(e){
              var thisChart = this;
              if (e[axisName]) {
                scope.$apply(function () {
                  scope.config[axisName].currentMin = e[axisName][0].min;
                  scope.config[axisName].currentMax = e[axisName][0].max;
                });
              } else {
                //handle reset button - zoom out to all
                scope.$apply(function () {
                  scope.config[axisName].currentMin = thisChart[axisName][0].dataMin;
                  scope.config[axisName].currentMax = thisChart[axisName][0].dataMax;
                });
              }
            });

            highchartsNGUtils.prependMethod(mergedOptions.chart.events, 'addSeries', function(e){
              scope.config[axisName].currentMin = this[axisName][0].min || scope.config[axisName].currentMin;
              scope.config[axisName].currentMax = this[axisName][0].max || scope.config[axisName].currentMax;
            });
          }
        }
      });

      if(config.title) {
        mergedOptions.title = config.title;
      }
      if (config.subtitle) {
        mergedOptions.subtitle = config.subtitle;
      }
      if (config.credits) {
        mergedOptions.credits = config.credits;
      }
      if(config.size) {
        if (config.size.width) {
          mergedOptions.chart.width = config.size.width;
        }
        if (config.size.height) {
          mergedOptions.chart.height = config.size.height;
        }
      }
      return mergedOptions;
    };

    var updateZoom = function (axis, modelAxis) {
      var extremes = axis.getExtremes();
      if(modelAxis.currentMin !== extremes.dataMin || modelAxis.currentMax !== extremes.dataMax) {
        axis.setExtremes(modelAxis.currentMin, modelAxis.currentMax, false);
      }
    };

    var processExtremes = function(chart, axis, axisName) {
      if(axis.currentMin || axis.currentMax) {
        chart[axisName][0].setExtremes(axis.currentMin, axis.currentMax, true);
      }
    };

    var chartOptionsWithoutEasyOptions = function (options) {
      return highchartsNGUtils.deepExtend({}, options, {data: null, visible: null});
    };

    var getChartType = function(scope) {
      if (scope.config === undefined) return 'Chart';
      return chartTypeMap[('' + scope.config.chartType).toLowerCase()] ||
             (scope.config.useHighStocks ? 'StockChart' : 'Chart');
    };

    return {
      restrict: 'EAC',
      replace: true,
      template: '<div></div>',
      scope: {
        config: '=',
        disableDataWatch: '='
      },
      link: function (scope, element, attrs) {
        // We keep some chart-specific variables here as a closure
        // instead of storing them on 'scope'.

        // prevSeriesOptions is maintained by processSeries
        var prevSeriesOptions = {};

        var processSeries = function(series) {
          var i;
          var ids = [];

          if(series) {
            var setIds = ensureIds(series);
            if(setIds) {
              //If we have set some ids this will trigger another digest cycle.
              //In this scenario just return early and let the next cycle take care of changes
              return false;
            }

            //Find series to add or update
            angular.forEach(series, function(s) {
              ids.push(s.id);
              var chartSeries = chart.get(s.id);
              if (chartSeries) {
                if (!angular.equals(prevSeriesOptions[s.id], chartOptionsWithoutEasyOptions(s))) {
                  chartSeries.update(angular.copy(s), false);
                } else {
                  if (s.visible !== undefined && chartSeries.visible !== s.visible) {
                    chartSeries.setVisible(s.visible, false);
                  }
                  chartSeries.setData(angular.copy(s.data), false);
                }
              } else {
                chart.addSeries(angular.copy(s), false);
              }
              prevSeriesOptions[s.id] = chartOptionsWithoutEasyOptions(s);
            });

            //  Shows no data text if all series are empty
            if(scope.config.noData) {
              var chartContainsData = false;

              for(i = 0; i < series.length; i++) {
                if (series[i].data && series[i].data.length > 0) {
                  chartContainsData = true;

                  break;
                }
              }

              if (!chartContainsData) {
                chart.showLoading(scope.config.noData);
              } else {
                chart.hideLoading();
              }
            }
          }

          //Now remove any missing series
          for(i = chart.series.length - 1; i >= 0; i--) {
            var s = chart.series[i];
            if (s.options.id !== 'highcharts-navigator-series' && highchartsNGUtils.indexOf(ids, s.options.id) < 0) {
              s.remove(false);
            }
          }

          return true;
        };

        // chart is maintained by initChart
        var chart = false;
        var initChart = function() {
          if (chart) chart.destroy();
          prevSeriesOptions = {};
          var config = scope.config || {};
          var mergedOptions = getMergedOptions(scope, element, config);
          var func = config.func || undefined;
          var chartType = getChartType(scope);

          chart = new Highcharts[chartType](mergedOptions, func);

          for (var i = 0; i < axisNames.length; i++) {
            if (config[axisNames[i]]) {
              processExtremes(chart, config[axisNames[i]], axisNames[i]);
            }
          }
          if(config.loading) {
            chart.showLoading();
          }
          config.getHighcharts = function() {
            return chart;
          };

        };
        initChart();


        if(scope.disableDataWatch){
          scope.$watchCollection('config.series', function (newSeries, oldSeries) {
            processSeries(newSeries);
            chart.redraw();
          });
        } else {
          scope.$watch('config.series', function (newSeries, oldSeries) {
            var needsRedraw = processSeries(newSeries);
            if(needsRedraw) {
              chart.redraw();
            }
          }, true);
        }

        scope.$watch('config.title', function (newTitle) {
          chart.setTitle(newTitle, true);
        }, true);

        scope.$watch('config.subtitle', function (newSubtitle) {
          chart.setTitle(true, newSubtitle);
        }, true);

        scope.$watch('config.loading', function (loading) {
          if(loading) {
            chart.showLoading(loading === true ? null : loading);
          } else {
            chart.hideLoading();
          }
        });
        scope.$watch('config.noData', function (noData) {
          if(scope.config && scope.config.loading) {
            chart.showLoading(noData);
          }
        }, true);

        scope.$watch('config.credits.enabled', function (enabled) {
          if (enabled) {
            chart.credits.show();
          } else if (chart.credits) {
            chart.credits.hide();
          }
        });

        scope.$watch(getChartType, function (chartType, oldChartType) {
          if (chartType === oldChartType) return;
          initChart();
        });

        angular.forEach(axisNames, function(axisName) {
          scope.$watch('config.' + axisName, function(newAxes, oldAxes) {
            if (newAxes === oldAxes || !newAxes) {
              return;
            }

            if (angular.isArray(newAxes)) {

              for (var axisIndex = 0; axisIndex < newAxes.length; axisIndex++) {
                var axis = newAxes[axisIndex];

                if (axisIndex < chart[axisName].length) {
                  chart[axisName][axisIndex].update(axis, false);
                  updateZoom(chart[axisName][axisIndex], angular.copy(axis));
                }

              }

            } else {
              // update single axis
              chart[axisName][0].update(newAxes, false);
              updateZoom(chart[axisName][0], angular.copy(newAxes));
            }

            chart.redraw();
          }, true);
        });
        scope.$watch('config.options', function (newOptions, oldOptions, scope) {
          //do nothing when called on registration
          if (newOptions === oldOptions) return;
          initChart();
          processSeries(scope.config.series);
          chart.redraw();
        }, true);

        scope.$watch('config.size', function (newSize, oldSize) {
          if(newSize === oldSize) return;
          if(newSize) {
            chart.setSize(newSize.width || undefined, newSize.height || undefined);
          }
        }, true);

        scope.$on('highchartsng.reflow', function () {
          chart.reflow();
        });

        scope.$on('$destroy', function() {
          if (chart) {
            try{
              chart.destroy();
            }catch(ex){
              // fail silently as highcharts will throw exception if element doesn't exist
            }

            $timeout(function(){
              element.remove();
            }, 0);
          }
        });

      }
    };
  }
}());

FileAPI = {
    //only one of jsPath or jsUrl.
    jsPath: '/OneKeyScripts/angularjs/modules/ng-file-upload/',
    //jsUrl: 'yourcdn.com/js/FileAPI.min.js',

    //only one of staticPath or flashUrl.
    staticPath: '/OneKeyScripts/angularjs/modules/ng-file-upload/',
    //flashUrl: 'yourcdn.com/js/FileAPI.flash.swf',

    //forceLoad: true, html5: false //to debug flash in HTML5 browsers
    //noContentTimeout: 10000 (see #528)
}
/*
 * angular-ui-bootstrap
 * http://angular-ui.github.io/bootstrap/

 * Version: 0.12.1 - 2015-02-20
 * License: MIT
 * Patch applied on 2015-04-15, based on https://github.com/angular-ui/bootstrap/pull/2942
 *  This patch allows configuration of the modal container element. 
 *  Modified from the Github pull request, to set modal-open on the body instead of container, so that 
 *   the user can't scroll the modal off the screen.
 */
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.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","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/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-unsafe-popup.html","template/tooltip/tooltip-popup.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]);
angular.module('ui.bootstrap.transition', [])

/**
 * $transition service provides a consistent interface to trigger CSS 3 transitions and to be informed when they complete.
 * @param  {DOMElement} element  The DOMElement that will be animated.
 * @param  {string|object|function} trigger  The thing that will cause the transition to start:
 *   - As a string, it represents the css class to be added to the element.
 *   - As an object, it represents a hash of style attributes to be applied to the element.
 *   - As a function, it represents a function to be called that will cause the transition to occur.
 * @return {Promise}  A promise that is resolved when the transition finishes.
 */
.factory('$transition', ['$q', '$timeout', '$rootScope', function($q, $timeout, $rootScope) {

  var $transition = function(element, trigger, options) {
    options = options || {};
    var deferred = $q.defer();
    var endEventName = $transition[options.animation ? 'animationEndEventName' : 'transitionEndEventName'];

    var transitionEndHandler = function(event) {
      $rootScope.$apply(function() {
        element.unbind(endEventName, transitionEndHandler);
        deferred.resolve(element);
      });
    };

    if (endEventName) {
      element.bind(endEventName, transitionEndHandler);
    }

    // Wrap in a timeout to allow the browser time to update the DOM before the transition is to occur
    $timeout(function() {
      if ( angular.isString(trigger) ) {
        element.addClass(trigger);
      } else if ( angular.isFunction(trigger) ) {
        trigger(element);
      } else if ( angular.isObject(trigger) ) {
        element.css(trigger);
      }
      //If browser does not support transitions, instantly resolve
      if ( !endEventName ) {
        deferred.resolve(element);
      }
    });

    // Add our custom cancel function to the promise that is returned
    // We can call this if we are about to run a new transition, which we know will prevent this transition from ending,
    // i.e. it will therefore never raise a transitionEnd event for that transition
    deferred.promise.cancel = function() {
      if ( endEventName ) {
        element.unbind(endEventName, transitionEndHandler);
      }
      deferred.reject('Transition cancelled');
    };

    return deferred.promise;
  };

  // Work out the name of the transitionEnd event
  var transElement = document.createElement('trans');
  var transitionEndEventNames = {
    'WebkitTransition': 'webkitTransitionEnd',
    'MozTransition': 'transitionend',
    'OTransition': 'oTransitionEnd',
    'transition': 'transitionend'
  };
  var animationEndEventNames = {
    'WebkitTransition': 'webkitAnimationEnd',
    'MozTransition': 'animationend',
    'OTransition': 'oAnimationEnd',
    'transition': 'animationend'
  };
  function findEndEventName(endEventNames) {
    for (var name in endEventNames){
      if (transElement.style[name] !== undefined) {
        return endEventNames[name];
      }
    }
  }
  $transition.transitionEndEventName = findEndEventName(transitionEndEventNames);
  $transition.animationEndEventName = findEndEventName(animationEndEventNames);
  return $transition;
}]);

angular.module('ui.bootstrap.collapse', ['ui.bootstrap.transition'])

  .directive('collapse', ['$transition', function ($transition) {

    return {
      link: function (scope, element, attrs) {

        var initialAnimSkip = true;
        var currentTransition;

        function doTransition(change) {
          var newTransition = $transition(element, change);
          if (currentTransition) {
            currentTransition.cancel();
          }
          currentTransition = newTransition;
          newTransition.then(newTransitionDone, newTransitionDone);
          return newTransition;

          function newTransitionDone() {
            // Make sure it's this transition, otherwise, leave it alone.
            if (currentTransition === newTransition) {
              currentTransition = undefined;
            }
          }
        }

        function expand() {
          if (initialAnimSkip) {
            initialAnimSkip = false;
            expandDone();
          } else {
            element.removeClass('collapse').addClass('collapsing');
            doTransition({ height: element[0].scrollHeight + 'px' }).then(expandDone);
          }
        }

        function expandDone() {
          element.removeClass('collapsing');
          element.addClass('collapse in');
          element.css({height: 'auto'});
        }

        function collapse() {
          if (initialAnimSkip) {
            initialAnimSkip = false;
            collapseDone();
            element.css({height: 0});
          } else {
            // CSS transitions don't work with height: auto, so we have to manually change the height to a specific value
            element.css({ height: element[0].scrollHeight + 'px' });
            //trigger reflow so a browser realizes that height was updated from auto to a specific value
            var x = element[0].offsetWidth;

            element.removeClass('collapse in').addClass('collapsing');

            doTransition({ height: 0 }).then(collapseDone);
          }
        }

        function collapseDone() {
          element.removeClass('collapsing');
          element.addClass('collapse');
        }

        scope.$watch(attrs.collapse, function (shouldCollapse) {
          if (shouldCollapse) {
            collapse();
          } else {
            expand();
          }
        });
      }
    };
  }]);

angular.module('ui.bootstrap.accordion', ['ui.bootstrap.collapse'])

.constant('accordionConfig', {
  closeOthers: true
})

.controller('AccordionController', ['$scope', '$attrs', 'accordionConfig', function ($scope, $attrs, accordionConfig) {

  // This array keeps track of the accordion groups
  this.groups = [];

  // Ensure that all the groups in this accordion are closed, unless close-others explicitly says not to
  this.closeOthers = function(openGroup) {
    var closeOthers = angular.isDefined($attrs.closeOthers) ? $scope.$eval($attrs.closeOthers) : accordionConfig.closeOthers;
    if ( closeOthers ) {
      angular.forEach(this.groups, function (group) {
        if ( group !== openGroup ) {
          group.isOpen = false;
        }
      });
    }
  };

  // This is called from the accordion-group directive to add itself to the accordion
  this.addGroup = function(groupScope) {
    var that = this;
    this.groups.push(groupScope);

    groupScope.$on('$destroy', function (event) {
      that.removeGroup(groupScope);
    });
  };

  // This is called from the accordion-group directive when to remove itself
  this.removeGroup = function(group) {
    var index = this.groups.indexOf(group);
    if ( index !== -1 ) {
      this.groups.splice(index, 1);
    }
  };

}])

// The accordion directive simply sets up the directive controller
// and adds an accordion CSS class to itself element.
.directive('accordion', function () {
  return {
    restrict:'EA',
    controller:'AccordionController',
    transclude: true,
    replace: false,
    templateUrl: 'template/accordion/accordion.html'
  };
})

// The accordion-group directive indicates a block of html that will expand and collapse in an accordion
.directive('accordionGroup', function() {
  return {
    require:'^accordion',         // We need this directive to be inside an accordion
    restrict:'EA',
    transclude:true,              // It transcludes the contents of the directive into the template
    replace: true,                // The element containing the directive will be replaced with the template
    templateUrl:'template/accordion/accordion-group.html',
    scope: {
      heading: '@',               // Interpolate the heading attribute onto this scope
      isOpen: '=?',
      isDisabled: '=?'
    },
    controller: function() {
      this.setHeading = function(element) {
        this.heading = element;
      };
    },
    link: function(scope, element, attrs, accordionCtrl) {
      accordionCtrl.addGroup(scope);

      scope.$watch('isOpen', function(value) {
        if ( value ) {
          accordionCtrl.closeOthers(scope);
        }
      });

      scope.toggleOpen = function() {
        if ( !scope.isDisabled ) {
          scope.isOpen = !scope.isOpen;
        }
      };
    }
  };
})

// Use accordion-heading below an accordion-group to provide a heading containing HTML
// <accordion-group>
//   <accordion-heading>Heading containing HTML - <img src="..."></accordion-heading>
// </accordion-group>
.directive('accordionHeading', function() {
  return {
    restrict: 'EA',
    transclude: true,   // Grab the contents to be used as the heading
    template: '',       // In effect remove this element!
    replace: true,
    require: '^accordionGroup',
    link: function(scope, element, attr, accordionGroupCtrl, transclude) {
      // Pass the heading to the accordion-group controller
      // so that it can be transcluded into the right place in the template
      // [The second parameter to transclude causes the elements to be cloned so that they work in ng-repeat]
      accordionGroupCtrl.setHeading(transclude(scope, function() {}));
    }
  };
})

// Use in the accordion-group template to indicate where you want the heading to be transcluded
// You must provide the property on the accordion-group controller that will hold the transcluded element
// <div class="accordion-group">
//   <div class="accordion-heading" ><a ... accordion-transclude="heading">...</a></div>
//   ...
// </div>
.directive('accordionTransclude', function() {
  return {
    require: '^accordionGroup',
    link: function(scope, element, attr, controller) {
      scope.$watch(function() { return controller[attr.accordionTransclude]; }, function(heading) {
        if ( heading ) {
          element.html('');
          element.append(heading);
        }
      });
    }
  };
});

angular.module('ui.bootstrap.alert', [])

.controller('AlertController', ['$scope', '$attrs', function ($scope, $attrs) {
  $scope.closeable = 'close' in $attrs;
  this.close = $scope.close;
}])

.directive('alert', function () {
  return {
    restrict:'EA',
    controller:'AlertController',
    templateUrl:'template/alert/alert.html',
    transclude:true,
    replace:true,
    scope: {
      type: '@',
      close: '&'
    }
  };
})

.directive('dismissOnTimeout', ['$timeout', function($timeout) {
  return {
    require: 'alert',
    link: function(scope, element, attrs, alertCtrl) {
      $timeout(function(){
        alertCtrl.close();
      }, parseInt(attrs.dismissOnTimeout, 10));
    }
  };
}]);

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', {
  activeClass: 'active',
  toggleEvent: 'click'
})

.controller('ButtonsController', ['buttonConfig', function(buttonConfig) {
  this.activeClass = buttonConfig.activeClass || 'active';
  this.toggleEvent = buttonConfig.toggleEvent || 'click';
}])

.directive('btnRadio', function () {
  return {
    require: ['btnRadio', 'ngModel'],
    controller: 'ButtonsController',
    link: function (scope, element, attrs, ctrls) {
      var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];

      //model -> UI
      ngModelCtrl.$render = function () {
        element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio)));
      };

      //ui->model
      element.bind(buttonsCtrl.toggleEvent, function () {
        var isActive = element.hasClass(buttonsCtrl.activeClass);

        if (!isActive || angular.isDefined(attrs.uncheckable)) {
          scope.$apply(function () {
            ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio));
            ngModelCtrl.$render();
          });
        }
      });
    }
  };
})

.directive('btnCheckbox', function () {
  return {
    require: ['btnCheckbox', 'ngModel'],
    controller: 'ButtonsController',
    link: function (scope, element, attrs, ctrls) {
      var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];

      function getTrueValue() {
        return getCheckboxValue(attrs.btnCheckboxTrue, true);
      }

      function getFalseValue() {
        return getCheckboxValue(attrs.btnCheckboxFalse, false);
      }

      function getCheckboxValue(attributeValue, defaultValue) {
        var val = scope.$eval(attributeValue);
        return angular.isDefined(val) ? val : defaultValue;
      }

      //model -> UI
      ngModelCtrl.$render = function () {
        element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
      };

      //ui->model
      element.bind(buttonsCtrl.toggleEvent, function () {
        scope.$apply(function () {
          ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());
          ngModelCtrl.$render();
        });
      });
    }
  };
});

/**
* @ngdoc overview
* @name ui.bootstrap.carousel
*
* @description
* AngularJS version of an image carousel.
*
*/
angular.module('ui.bootstrap.carousel', ['ui.bootstrap.transition'])
.controller('CarouselController', ['$scope', '$timeout', '$interval', '$transition', function ($scope, $timeout, $interval, $transition) {
  var self = this,
    slides = self.slides = $scope.slides = [],
    currentIndex = -1,
    currentInterval, isPlaying;
  self.currentSlide = null;

  var destroyed = false;
  /* direction: "prev" or "next" */
  self.select = $scope.select = function(nextSlide, direction) {
    var nextIndex = slides.indexOf(nextSlide);
    //Decide direction if it's not given
    if (direction === undefined) {
      direction = nextIndex > currentIndex ? 'next' : 'prev';
    }
    if (nextSlide && nextSlide !== self.currentSlide) {
      if ($scope.$currentTransition) {
        $scope.$currentTransition.cancel();
        //Timeout so ng-class in template has time to fix classes for finished slide
        $timeout(goNext);
      } else {
        goNext();
      }
    }
    function goNext() {
      // Scope has been destroyed, stop here.
      if (destroyed) { return; }
      //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) {
        //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);
        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) {
          angular.extend(slide, {direction: '', entering: false, leaving: false, active: false});
        });
        angular.extend(nextSlide, {direction: direction, active: true, entering: true});
        angular.extend(self.currentSlide||{}, {direction: direction, leaving: true});

        $scope.$currentTransition = $transition(nextSlide.$element, {});
        //We have to create new pointers inside a closure since next & current will change
        (function(next,current) {
          $scope.$currentTransition.then(
            function(){ transitionDone(next, current); },
            function(){ transitionDone(next, current); }
          );
        }(nextSlide, self.currentSlide));
      } else {
        transitionDone(nextSlide, self.currentSlide);
      }
      self.currentSlide = nextSlide;
      currentIndex = nextIndex;
      //every time you change slides, reset the timer
      restartTimer();
    }
    function transitionDone(next, current) {
      angular.extend(next, {direction: '', active: true, leaving: false, entering: false});
      angular.extend(current||{}, {direction: '', active: false, leaving: false, entering: false});
      $scope.$currentTransition = null;
    }
  };
  $scope.$on('$destroy', function () {
    destroyed = true;
  });

  /* Allow outside people to call indexOf on slides array */
  self.indexOfSlide = function(slide) {
    return slides.indexOf(slide);
  };

  $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');
    }
  };

  $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');
    }
  };

  $scope.isActive = function(slide) {
     return self.currentSlide === slide;
  };

  $scope.$watch('interval', restartTimer);
  $scope.$on('$destroy', resetTimer);

  function restartTimer() {
    resetTimer();
    var interval = +$scope.interval;
    if (!isNaN(interval) && interval > 0) {
      currentInterval = $interval(timerFn, interval);
    }
  }

  function resetTimer() {
    if (currentInterval) {
      $interval.cancel(currentInterval);
      currentInterval = null;
    }
  }

  function timerFn() {
    var interval = +$scope.interval;
    if (isPlaying && !isNaN(interval) && interval > 0) {
      $scope.next();
    } else {
      $scope.pause();
    }
  }

  $scope.play = function() {
    if (!isPlaying) {
      isPlaying = true;
      restartTimer();
    }
  };
  $scope.pause = function() {
    if (!$scope.noPause) {
      isPlaying = false;
      resetTimer();
    }
  };

  self.addSlide = function(slide, element) {
    slide.$element = element;
    slides.push(slide);
    //if this is the first slide or the slide is set to active, select it
    if(slides.length === 1 || slide.active) {
      self.select(slides[slides.length-1]);
      if (slides.length == 1) {
        $scope.play();
      }
    } else {
      slide.active = false;
    }
  };

  self.removeSlide = function(slide) {
    //get the index of the slide inside the carousel
    var index = slides.indexOf(slide);
    slides.splice(index, 1);
    if (slides.length > 0 && slide.active) {
      if (index >= slides.length) {
        self.select(slides[index-1]);
      } else {
        self.select(slides[index]);
      }
    } else if (currentIndex > index) {
      currentIndex--;
    }
  };

}])

/**
 * @ngdoc directive
 * @name ui.bootstrap.carousel.directive:carousel
 * @restrict EA
 *
 * @description
 * Carousel is the outer container for a set of image 'slides' to showcase.
 *
 * @param {number=} interval The time, in milliseconds, that it will take the carousel to go to the next slide.
 * @param {boolean=} noTransition Whether to disable transitions on the carousel.
 * @param {boolean=} noPause Whether to disable pausing on the carousel (by default, the carousel interval pauses on hover).
 *
 * @example
<example module="ui.bootstrap">
  <file name="index.html">
    <carousel>
      <slide>
        <img src="https://placekitten.com/150/150" style="margin:auto;">
        <div class="carousel-caption">
          <p>Beautiful!</p>
        </div>
      </slide>
      <slide>
        <img src="https://placekitten.com/100/150" style="margin:auto;">
        <div class="carousel-caption">
          <p>D'aww!</p>
        </div>
      </slide>
    </carousel>
  </file>
  <file name="demo.css">
    .carousel-indicators {
      top: auto;
      bottom: 15px;
    }
  </file>
</example>
 */
.directive('carousel', [function() {
  return {
    restrict: 'EA',
    transclude: true,
    replace: true,
    controller: 'CarouselController',
    require: 'carousel',
    templateUrl: 'template/carousel/carousel.html',
    scope: {
      interval: '=',
      noTransition: '=',
      noPause: '='
    }
  };
}])

/**
 * @ngdoc directive
 * @name ui.bootstrap.carousel.directive:slide
 * @restrict EA
 *
 * @description
 * Creates a slide inside a {@link ui.bootstrap.carousel.directive:carousel carousel}.  Must be placed as a child of a carousel element.
 *
 * @param {boolean=} active Model binding, whether or not this slide is currently active.
 *
 * @example
<example module="ui.bootstrap">
  <file name="index.html">
<div ng-controller="CarouselDemoCtrl">
  <carousel>
    <slide ng-repeat="slide in slides" active="slide.active">
      <img ng-src="{{slide.image}}" style="margin:auto;">
      <div class="carousel-caption">
        <h4>Slide {{$index}}</h4>
        <p>{{slide.text}}</p>
      </div>
    </slide>
  </carousel>
  Interval, in milliseconds: <input type="number" ng-model="myInterval">
  <br />Enter a negative number to stop the interval.
</div>
  </file>
  <file name="script.js">
function CarouselDemoCtrl($scope) {
  $scope.myInterval = 5000;
}
  </file>
  <file name="demo.css">
    .carousel-indicators {
      top: auto;
      bottom: 15px;
    }
  </file>
</example>
*/

.directive('slide', function() {
  return {
    require: '^carousel',
    restrict: 'EA',
    transclude: true,
    replace: true,
    templateUrl: 'template/carousel/slide.html',
    scope: {
      active: '=?'
    },
    link: function (scope, element, attrs, carouselCtrl) {
      carouselCtrl.addSlide(scope, element);
      //when the scope is destroyed then remove the slide from the current slides array
      scope.$on('$destroy', function() {
        carouselCtrl.removeSlide(scope);
      });

      scope.$watch('active', function(active) {
        if (active) {
          carouselCtrl.select(scope);
        }
      });
    }
  };
});

angular.module('ui.bootstrap.dateparser', [])

.service('dateParser', ['$locale', 'orderByFilter', function($locale, orderByFilter) {

  this.parsers = {};

  var formatCodeToRegex = {
    'yyyy': {
      regex: '\\d{4}',
      apply: function(value) { this.year = +value; }
    },
    'yy': {
      regex: '\\d{2}',
      apply: function(value) { this.year = +value + 2000; }
    },
    'y': {
      regex: '\\d{1,4}',
      apply: function(value) { this.year = +value; }
    },
    'MMMM': {
      regex: $locale.DATETIME_FORMATS.MONTH.join('|'),
      apply: function(value) { this.month = $locale.DATETIME_FORMATS.MONTH.indexOf(value); }
    },
    'MMM': {
      regex: $locale.DATETIME_FORMATS.SHORTMONTH.join('|'),
      apply: function(value) { this.month = $locale.DATETIME_FORMATS.SHORTMONTH.indexOf(value); }
    },
    'MM': {
      regex: '0[1-9]|1[0-2]',
      apply: function(value) { this.month = value - 1; }
    },
    'M': {
      regex: '[1-9]|1[0-2]',
      apply: function(value) { this.month = value - 1; }
    },
    'dd': {
      regex: '[0-2][0-9]{1}|3[0-1]{1}',
      apply: function(value) { this.date = +value; }
    },
    'd': {
      regex: '[1-2]?[0-9]{1}|3[0-1]{1}',
      apply: function(value) { this.date = +value; }
    },
    'EEEE': {
      regex: $locale.DATETIME_FORMATS.DAY.join('|')
    },
    'EEE': {
      regex: $locale.DATETIME_FORMATS.SHORTDAY.join('|')
    }
  };

  function createParser(format) {
    var map = [], regex = format.split('');

    angular.forEach(formatCodeToRegex, function(data, code) {
      var index = format.indexOf(code);

      if (index > -1) {
        format = format.split('');

        regex[index] = '(' + data.regex + ')';
        format[index] = '$'; // Custom symbol to define consumed part of format
        for (var i = index + 1, n = index + code.length; i < n; i++) {
          regex[i] = '';
          format[i] = '$';
        }
        format = format.join('');

        map.push({ index: index, apply: data.apply });
      }
    });

    return {
      regex: new RegExp('^' + regex.join('') + '$'),
      map: orderByFilter(map, 'index')
    };
  }

  this.parse = function(input, format) {
    if ( !angular.isString(input) || !format ) {
      return input;
    }

    format = $locale.DATETIME_FORMATS[format] || format;

    if ( !this.parsers[format] ) {
      this.parsers[format] = createParser(format);
    }

    var parser = this.parsers[format],
        regex = parser.regex,
        map = parser.map,
        results = input.match(regex);

    if ( results && results.length ) {
      var fields = { year: 1900, month: 0, date: 1, hours: 0 }, dt;

      for( var i = 1, n = results.length; i < n; i++ ) {
        var mapper = map[i-1];
        if ( mapper.apply ) {
          mapper.apply.call(fields, results[i]);
        }
      }

      if ( isValid(fields.year, fields.month, fields.date) ) {
        dt = new Date( fields.year, fields.month, fields.date, fields.hours);
      }

      return dt;
    }
  };

  // Check if date is valid for specific month (and year for February).
  // Month: 0 = Jan, 1 = Feb, etc
  function isValid(year, month, date) {
    if ( month === 1 && date > 28) {
        return date === 29 && ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);
    }

    if ( month === 3 || month === 5 || month === 8 || month === 10) {
        return date < 31;
    }

    return true;
  }
}]);

angular.module('ui.bootstrap.position', [])

/**
 * A set of utility methods that can be use to retrieve position of DOM elements.
 * It is meant to be used where we need to absolute-position DOM elements in
 * relation to other, existing elements (this is the case for tooltips, popovers,
 * typeahead suggestions etc.).
 */
  .factory('$position', ['$document', '$window', function ($document, $window) {

    function getStyle(el, cssprop) {
      if (el.currentStyle) { //IE
        return el.currentStyle[cssprop];
      } else if ($window.getComputedStyle) {
        return $window.getComputedStyle(el)[cssprop];
      }
      // finally try and get inline style
      return el.style[cssprop];
    }

    /**
     * Checks if a given element is statically positioned
     * @param element - raw DOM element
     */
    function isStaticPositioned(element) {
      return (getStyle(element, 'position') || 'static' ) === 'static';
    }

    /**
     * returns the closest, non-statically positioned parentOffset of a given element
     * @param element
     */
    var parentOffsetEl = function (element) {
      var docDomEl = $document[0];
      var offsetParent = element.offsetParent || docDomEl;
      while (offsetParent && offsetParent !== docDomEl && isStaticPositioned(offsetParent) ) {
        offsetParent = offsetParent.offsetParent;
      }
      return offsetParent || docDomEl;
    };

    return {
      /**
       * Provides read-only equivalent of jQuery's position function:
       * http://api.jquery.com/position/
       */
      position: function (element) {
        var elBCR = this.offset(element);
        var offsetParentBCR = { top: 0, left: 0 };
        var offsetParentEl = parentOffsetEl(element[0]);
        if (offsetParentEl != $document[0]) {
          offsetParentBCR = this.offset(angular.element(offsetParentEl));
          offsetParentBCR.top += offsetParentEl.clientTop - offsetParentEl.scrollTop;
          offsetParentBCR.left += offsetParentEl.clientLeft - offsetParentEl.scrollLeft;
        }

        var boundingClientRect = element[0].getBoundingClientRect();
        return {
          width: boundingClientRect.width || element.prop('offsetWidth'),
          height: boundingClientRect.height || element.prop('offsetHeight'),
          top: elBCR.top - offsetParentBCR.top,
          left: elBCR.left - offsetParentBCR.left
        };
      },

      /**
       * Provides read-only equivalent of jQuery's offset function:
       * http://api.jquery.com/offset/
       */
      offset: function (element) {
        var boundingClientRect = element[0].getBoundingClientRect();
        return {
          width: boundingClientRect.width || element.prop('offsetWidth'),
          height: boundingClientRect.height || element.prop('offsetHeight'),
          top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop),
          left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft)
        };
      },

      /**
       * Provides coordinates for the targetEl in relation to hostEl
       */
      positionElements: function (hostEl, targetEl, positionStr, appendToBody) {

        var positionStrParts = positionStr.split('-');
        var pos0 = positionStrParts[0], pos1 = positionStrParts[1] || 'center';

        var hostElPos,
          targetElWidth,
          targetElHeight,
          targetElPos;

        hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl);

        targetElWidth = targetEl.prop('offsetWidth');
        targetElHeight = targetEl.prop('offsetHeight');

        var shiftWidth = {
          center: function () {
            return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2;
          },
          left: function () {
            return hostElPos.left;
          },
          right: function () {
            return hostElPos.left + hostElPos.width;
          }
        };

        var shiftHeight = {
          center: function () {
            return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2;
          },
          top: function () {
            return hostElPos.top;
          },
          bottom: function () {
            return hostElPos.top + hostElPos.height;
          }
        };

        switch (pos0) {
          case 'right':
            targetElPos = {
              top: shiftHeight[pos1](),
              left: shiftWidth[pos0]()
            };
            break;
          case 'left':
            targetElPos = {
              top: shiftHeight[pos1](),
              left: hostElPos.left - targetElWidth
            };
            break;
          case 'bottom':
            targetElPos = {
              top: shiftHeight[pos0](),
              left: shiftWidth[pos1]()
            };
            break;
          default:
            targetElPos = {
              top: hostElPos.top - targetElHeight,
              left: shiftWidth[pos1]()
            };
            break;
        }

        return targetElPos;
      }
    };
  }]);

angular.module('ui.bootstrap.datepicker', ['ui.bootstrap.dateparser', 'ui.bootstrap.position'])

.constant('datepickerConfig', {
  formatDay: 'dd',
  formatMonth: 'MMMM',
  formatYear: 'yyyy',
  formatDayHeader: 'EEE',
  formatDayTitle: 'MMMM yyyy',
  formatMonthTitle: 'yyyy',
  datepickerMode: 'day',
  minMode: 'day',
  maxMode: 'year',
  showWeeks: true,
  startingDay: 0,
  yearRange: 20,
  minDate: null,
  maxDate: null
})

.controller('DatepickerController', ['$scope', '$attrs', '$parse', '$interpolate', '$timeout', '$log', 'dateFilter', 'datepickerConfig', function($scope, $attrs, $parse, $interpolate, $timeout, $log, dateFilter, datepickerConfig) {
  var self = this,
      ngModelCtrl = { $setViewValue: angular.noop }; // nullModelCtrl;

  // Modes chain
  this.modes = ['day', 'month', 'year'];

  // Configuration attributes
  angular.forEach(['formatDay', 'formatMonth', 'formatYear', 'formatDayHeader', 'formatDayTitle', 'formatMonthTitle',
                   'minMode', 'maxMode', 'showWeeks', 'startingDay', 'yearRange'], function( key, index ) {
    self[key] = angular.isDefined($attrs[key]) ? (index < 8 ? $interpolate($attrs[key])($scope.$parent) : $scope.$parent.$eval($attrs[key])) : datepickerConfig[key];
  });

  // Watchable date attributes
  angular.forEach(['minDate', 'maxDate'], function( key ) {
    if ( $attrs[key] ) {
      $scope.$parent.$watch($parse($attrs[key]), function(value) {
        self[key] = value ? new Date(value) : null;
        self.refreshView();
      });
    } else {
      self[key] = datepickerConfig[key] ? new Date(datepickerConfig[key]) : null;
    }
  });

  $scope.datepickerMode = $scope.datepickerMode || datepickerConfig.datepickerMode;
  $scope.uniqueId = 'datepicker-' + $scope.$id + '-' + Math.floor(Math.random() * 10000);
  this.activeDate = angular.isDefined($attrs.initDate) ? $scope.$parent.$eval($attrs.initDate) : new Date();

  $scope.isActive = function(dateObject) {
    if (self.compare(dateObject.date, self.activeDate) === 0) {
      $scope.activeDateId = dateObject.uid;
      return true;
    }
    return false;
  };

  this.init = function( ngModelCtrl_ ) {
    ngModelCtrl = ngModelCtrl_;

    ngModelCtrl.$render = function() {
      self.render();
    };
  };

  this.render = function() {
    if ( ngModelCtrl.$modelValue ) {
      var date = new Date( ngModelCtrl.$modelValue ),
          isValid = !isNaN(date);

      if ( isValid ) {
        this.activeDate = date;
      } else {
        $log.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.');
      }
      ngModelCtrl.$setValidity('date', isValid);
    }
    this.refreshView();
  };

  this.refreshView = function() {
    if ( this.element ) {
      this._refreshView();

      var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null;
      ngModelCtrl.$setValidity('date-disabled', !date || (this.element && !this.isDisabled(date)));
    }
  };

  this.createDateObject = function(date, format) {
    var model = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null;
    return {
      date: date,
      label: dateFilter(date, format),
      selected: model && this.compare(date, model) === 0,
      disabled: this.isDisabled(date),
      current: this.compare(date, new Date()) === 0
    };
  };

  this.isDisabled = function( date ) {
    return ((this.minDate && this.compare(date, this.minDate) < 0) || (this.maxDate && this.compare(date, this.maxDate) > 0) || ($attrs.dateDisabled && $scope.dateDisabled({date: date, mode: $scope.datepickerMode})));
  };

  // Split array into smaller arrays
  this.split = function(arr, size) {
    var arrays = [];
    while (arr.length > 0) {
      arrays.push(arr.splice(0, size));
    }
    return arrays;
  };

  $scope.select = function( date ) {
    if ( $scope.datepickerMode === self.minMode ) {
      var dt = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : new Date(0, 0, 0, 0, 0, 0, 0);
      dt.setFullYear( date.getFullYear(), date.getMonth(), date.getDate() );
      ngModelCtrl.$setViewValue( dt );
      ngModelCtrl.$render();
    } else {
      self.activeDate = date;
      $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) - 1 ];
    }
  };

  $scope.move = function( direction ) {
    var year = self.activeDate.getFullYear() + direction * (self.step.years || 0),
        month = self.activeDate.getMonth() + direction * (self.step.months || 0);
    self.activeDate.setFullYear(year, month, 1);
    self.refreshView();
  };

  $scope.toggleMode = function( direction ) {
    direction = direction || 1;

    if (($scope.datepickerMode === self.maxMode && direction === 1) || ($scope.datepickerMode === self.minMode && direction === -1)) {
      return;
    }

    $scope.datepickerMode = self.modes[ self.modes.indexOf( $scope.datepickerMode ) + direction ];
  };

  // Key event mapper
  $scope.keys = { 13:'enter', 32:'space', 33:'pageup', 34:'pagedown', 35:'end', 36:'home', 37:'left', 38:'up', 39:'right', 40:'down' };

  var focusElement = function() {
    $timeout(function() {
      self.element[0].focus();
    }, 0 , false);
  };

  // Listen for focus requests from popup directive
  $scope.$on('datepicker.focus', focusElement);

  $scope.keydown = function( evt ) {
    var key = $scope.keys[evt.which];

    if ( !key || evt.shiftKey || evt.altKey ) {
      return;
    }

    evt.preventDefault();
    evt.stopPropagation();

    if (key === 'enter' || key === 'space') {
      if ( self.isDisabled(self.activeDate)) {
        return; // do nothing
      }
      $scope.select(self.activeDate);
      focusElement();
    } else if (evt.ctrlKey && (key === 'up' || key === 'down')) {
      $scope.toggleMode(key === 'up' ? 1 : -1);
      focusElement();
    } else {
      self.handleKeyDown(key, evt);
      self.refreshView();
    }
  };
}])

.directive( 'datepicker', function () {
  return {
    restrict: 'EA',
    replace: true,
    templateUrl: 'template/datepicker/datepicker.html',
    scope: {
      datepickerMode: '=?',
      dateDisabled: '&'
    },
    require: ['datepicker', '?^ngModel'],
    controller: 'DatepickerController',
    link: function(scope, element, attrs, ctrls) {
      var datepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];

      if ( ngModelCtrl ) {
        datepickerCtrl.init( ngModelCtrl );
      }
    }
  };
})

.directive('daypicker', ['dateFilter', function (dateFilter) {
  return {
    restrict: 'EA',
    replace: true,
    templateUrl: 'template/datepicker/day.html',
    require: '^datepicker',
    link: function(scope, element, attrs, ctrl) {
      scope.showWeeks = ctrl.showWeeks;

      ctrl.step = { months: 1 };
      ctrl.element = element;

      var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
      function getDaysInMonth( year, month ) {
        return ((month === 1) && (year % 4 === 0) && ((year % 100 !== 0) || (year % 400 === 0))) ? 29 : DAYS_IN_MONTH[month];
      }

      function getDates(startDate, n) {
        var dates = new Array(n), current = new Date(startDate), i = 0;
        current.setHours(12); // Prevent repeated dates because of timezone bug
        while ( i < n ) {
          dates[i++] = new Date(current);
          current.setDate( current.getDate() + 1 );
        }
        return dates;
      }

      ctrl._refreshView = function() {
        var year = ctrl.activeDate.getFullYear(),
          month = ctrl.activeDate.getMonth(),
          firstDayOfMonth = new Date(year, month, 1),
          difference = ctrl.startingDay - firstDayOfMonth.getDay(),
          numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : - difference,
          firstDate = new Date(firstDayOfMonth);

        if ( numDisplayedFromPreviousMonth > 0 ) {
          firstDate.setDate( - numDisplayedFromPreviousMonth + 1 );
        }

        // 42 is the number of days on a six-month calendar
        var days = getDates(firstDate, 42);
        for (var i = 0; i < 42; i ++) {
          days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), {
            secondary: days[i].getMonth() !== month,
            uid: scope.uniqueId + '-' + i
          });
        }

        scope.labels = new Array(7);
        for (var j = 0; j < 7; j++) {
          scope.labels[j] = {
            abbr: dateFilter(days[j].date, ctrl.formatDayHeader),
            full: dateFilter(days[j].date, 'EEEE')
          };
        }

        scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle);
        scope.rows = ctrl.split(days, 7);

        if ( scope.showWeeks ) {
          scope.weekNumbers = [];
          var weekNumber = getISO8601WeekNumber( scope.rows[0][0].date ),
              numWeeks = scope.rows.length;
          while( scope.weekNumbers.push(weekNumber++) < numWeeks ) {}
        }
      };

      ctrl.compare = function(date1, date2) {
        return (new Date( date1.getFullYear(), date1.getMonth(), date1.getDate() ) - new Date( date2.getFullYear(), date2.getMonth(), date2.getDate() ) );
      };

      function getISO8601WeekNumber(date) {
        var checkDate = new Date(date);
        checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); // Thursday
        var time = checkDate.getTime();
        checkDate.setMonth(0); // Compare with Jan 1
        checkDate.setDate(1);
        return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
      }

      ctrl.handleKeyDown = function( key, evt ) {
        var date = ctrl.activeDate.getDate();

        if (key === 'left') {
          date = date - 1;   // up
        } else if (key === 'up') {
          date = date - 7;   // down
        } else if (key === 'right') {
          date = date + 1;   // down
        } else if (key === 'down') {
          date = date + 7;
        } else if (key === 'pageup' || key === 'pagedown') {
          var month = ctrl.activeDate.getMonth() + (key === 'pageup' ? - 1 : 1);
          ctrl.activeDate.setMonth(month, 1);
          date = Math.min(getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth()), date);
        } else if (key === 'home') {
          date = 1;
        } else if (key === 'end') {
          date = getDaysInMonth(ctrl.activeDate.getFullYear(), ctrl.activeDate.getMonth());
        }
        ctrl.activeDate.setDate(date);
      };

      ctrl.refreshView();
    }
  };
}])

.directive('monthpicker', ['dateFilter', function (dateFilter) {
  return {
    restrict: 'EA',
    replace: true,
    templateUrl: 'template/datepicker/month.html',
    require: '^datepicker',
    link: function(scope, element, attrs, ctrl) {
      ctrl.step = { years: 1 };
      ctrl.element = element;

      ctrl._refreshView = function() {
        var months = new Array(12),
            year = ctrl.activeDate.getFullYear();

        for ( var i = 0; i < 12; i++ ) {
          months[i] = angular.extend(ctrl.createDateObject(new Date(year, i, 1), ctrl.formatMonth), {
            uid: scope.uniqueId + '-' + i
          });
        }

        scope.title = dateFilter(ctrl.activeDate, ctrl.formatMonthTitle);
        scope.rows = ctrl.split(months, 3);
      };

      ctrl.compare = function(date1, date2) {
        return new Date( date1.getFullYear(), date1.getMonth() ) - new Date( date2.getFullYear(), date2.getMonth() );
      };

      ctrl.handleKeyDown = function( key, evt ) {
        var date = ctrl.activeDate.getMonth();

        if (key === 'left') {
          date = date - 1;   // up
        } else if (key === 'up') {
          date = date - 3;   // down
        } else if (key === 'right') {
          date = date + 1;   // down
        } else if (key === 'down') {
          date = date + 3;
        } else if (key === 'pageup' || key === 'pagedown') {
          var year = ctrl.activeDate.getFullYear() + (key === 'pageup' ? - 1 : 1);
          ctrl.activeDate.setFullYear(year);
        } else if (key === 'home') {
          date = 0;
        } else if (key === 'end') {
          date = 11;
        }
        ctrl.activeDate.setMonth(date);
      };

      ctrl.refreshView();
    }
  };
}])

.directive('yearpicker', ['dateFilter', function (dateFilter) {
  return {
    restrict: 'EA',
    replace: true,
    templateUrl: 'template/datepicker/year.html',
    require: '^datepicker',
    link: function(scope, element, attrs, ctrl) {
      var range = ctrl.yearRange;

      ctrl.step = { years: range };
      ctrl.element = element;

      function getStartingYear( year ) {
        return parseInt((year - 1) / range, 10) * range + 1;
      }

      ctrl._refreshView = function() {
        var years = new Array(range);

        for ( var i = 0, start = getStartingYear(ctrl.activeDate.getFullYear()); i < range; i++ ) {
          years[i] = angular.extend(ctrl.createDateObject(new Date(start + i, 0, 1), ctrl.formatYear), {
            uid: scope.uniqueId + '-' + i
          });
        }

        scope.title = [years[0].label, years[range - 1].label].join(' - ');
        scope.rows = ctrl.split(years, 5);
      };

      ctrl.compare = function(date1, date2) {
        return date1.getFullYear() - date2.getFullYear();
      };

      ctrl.handleKeyDown = function( key, evt ) {
        var date = ctrl.activeDate.getFullYear();

        if (key === 'left') {
          date = date - 1;   // up
        } else if (key === 'up') {
          date = date - 5;   // down
        } else if (key === 'right') {
          date = date + 1;   // down
        } else if (key === 'down') {
          date = date + 5;
        } else if (key === 'pageup' || key === 'pagedown') {
          date += (key === 'pageup' ? - 1 : 1) * ctrl.step.years;
        } else if (key === 'home') {
          date = getStartingYear( ctrl.activeDate.getFullYear() );
        } else if (key === 'end') {
          date = getStartingYear( ctrl.activeDate.getFullYear() ) + range - 1;
        }
        ctrl.activeDate.setFullYear(date);
      };

      ctrl.refreshView();
    }
  };
}])

.constant('datepickerPopupConfig', {
  datepickerPopup: 'yyyy-MM-dd',
  currentText: 'Today',
  clearText: 'Clear',
  closeText: 'Done',
  closeOnDateSelection: true,
  appendToBody: false,
  showButtonBar: true
})

.directive('datepickerPopup', ['$compile', '$parse', '$document', '$position', 'dateFilter', 'dateParser', 'datepickerPopupConfig',
function ($compile, $parse, $document, $position, dateFilter, dateParser, datepickerPopupConfig) {
  return {
    restrict: 'EA',
    require: 'ngModel',
    scope: {
      isOpen: '=?',
      currentText: '@',
      clearText: '@',
      closeText: '@',
      dateDisabled: '&'
    },
    link: function(scope, element, attrs, ngModel) {
      var dateFormat,
          closeOnDateSelection = angular.isDefined(attrs.closeOnDateSelection) ? scope.$parent.$eval(attrs.closeOnDateSelection) : datepickerPopupConfig.closeOnDateSelection,
          appendToBody = angular.isDefined(attrs.datepickerAppendToBody) ? scope.$parent.$eval(attrs.datepickerAppendToBody) : datepickerPopupConfig.appendToBody;

      scope.showButtonBar = angular.isDefined(attrs.showButtonBar) ? scope.$parent.$eval(attrs.showButtonBar) : datepickerPopupConfig.showButtonBar;

      scope.getText = function( key ) {
        return scope[key + 'Text'] || datepickerPopupConfig[key + 'Text'];
      };

      attrs.$observe('datepickerPopup', function(value) {
          dateFormat = value || datepickerPopupConfig.datepickerPopup;
          ngModel.$render();
      });

      // popup element used to display calendar
      var popupEl = angular.element('<div datepicker-popup-wrap><div datepicker></div></div>');
      popupEl.attr({
        'ng-model': 'date',
        'ng-change': 'dateSelection()'
      });

      function cameltoDash( string ){
        return string.replace(/([A-Z])/g, function($1) { return '-' + $1.toLowerCase(); });
      }

      // datepicker element
      var datepickerEl = angular.element(popupEl.children()[0]);
      if ( attrs.datepickerOptions ) {
        angular.forEach(scope.$parent.$eval(attrs.datepickerOptions), function( value, option ) {
          datepickerEl.attr( cameltoDash(option), value );
        });
      }

      scope.watchData = {};
      angular.forEach(['minDate', 'maxDate', 'datepickerMode'], function( key ) {
        if ( attrs[key] ) {
          var getAttribute = $parse(attrs[key]);
          scope.$parent.$watch(getAttribute, function(value){
            scope.watchData[key] = value;
          });
          datepickerEl.attr(cameltoDash(key), 'watchData.' + key);

          // Propagate changes from datepicker to outside
          if ( key === 'datepickerMode' ) {
            var setAttribute = getAttribute.assign;
            scope.$watch('watchData.' + key, function(value, oldvalue) {
              if ( value !== oldvalue ) {
                setAttribute(scope.$parent, value);
              }
            });
          }
        }
      });
      if (attrs.dateDisabled) {
        datepickerEl.attr('date-disabled', 'dateDisabled({ date: date, mode: mode })');
      }

      function parseDate(viewValue) {
        if (!viewValue) {
          ngModel.$setValidity('date', true);
          return null;
        } else if (angular.isDate(viewValue) && !isNaN(viewValue)) {
          ngModel.$setValidity('date', true);
          return viewValue;
        } else if (angular.isString(viewValue)) {
          var date = dateParser.parse(viewValue, dateFormat) || 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(dt) {
        if (angular.isDefined(dt)) {
          scope.date = dt;
        }
        ngModel.$setViewValue(scope.date);
        ngModel.$render();

        if ( closeOnDateSelection ) {
          scope.isOpen = false;
          element[0].focus();
        }
      };

      element.bind('input change keyup', function() {
        scope.$apply(function() {
          scope.date = ngModel.$modelValue;
        });
      });

      // Outter change
      ngModel.$render = function() {
        var date = ngModel.$viewValue ? dateFilter(ngModel.$viewValue, dateFormat) : '';
        element.val(date);
        scope.date = parseDate( ngModel.$modelValue );
      };

      var documentClickBind = function(event) {
        if (scope.isOpen && event.target !== element[0]) {
          scope.$apply(function() {
            scope.isOpen = false;
          });
        }
      };

      var keydown = function(evt, noApply) {
        scope.keydown(evt);
      };
      element.bind('keydown', keydown);

      scope.keydown = function(evt) {
        if (evt.which === 27) {
          evt.preventDefault();
          evt.stopPropagation();
          scope.close();
        } else if (evt.which === 40 && !scope.isOpen) {
          scope.isOpen = true;
        }
      };

      scope.$watch('isOpen', function(value) {
        if (value) {
          scope.$broadcast('datepicker.focus');
          scope.position = appendToBody ? $position.offset(element) : $position.position(element);
          scope.position.top = scope.position.top + element.prop('offsetHeight');

          $document.bind('click', documentClickBind);
        } else {
          $document.unbind('click', documentClickBind);
        }
      });

      scope.select = function( date ) {
        if (date === 'today') {
          var today = new Date();
          if (angular.isDate(ngModel.$modelValue)) {
            date = new Date(ngModel.$modelValue);
            date.setFullYear(today.getFullYear(), today.getMonth(), today.getDate());
          } else {
            date = new Date(today.setHours(0, 0, 0, 0));
          }
        }
        scope.dateSelection( date );
      };

      scope.close = function() {
        scope.isOpen = false;
        element[0].focus();
      };

      var $popup = $compile(popupEl)(scope);
      // Prevent jQuery cache memory leak (template is now redundant after linking)
      popupEl.remove();

      if ( appendToBody ) {
        $document.find('body').append($popup);
      } else {
        element.after($popup);
      }

      scope.$on('$destroy', function() {
        $popup.remove();
        element.unbind('keydown', keydown);
        $document.unbind('click', documentClickBind);
      });
    }
  };
}])

.directive('datepickerPopupWrap', function() {
  return {
    restrict:'EA',
    replace: true,
    transclude: true,
    templateUrl: 'template/datepicker/popup.html',
    link:function (scope, element, attrs) {
      element.bind('click', function(event) {
        event.preventDefault();
        event.stopPropagation();
      });
    }
  };
});

angular.module('ui.bootstrap.dropdown', [])

.constant('dropdownConfig', {
  openClass: 'open'
})

.service('dropdownService', ['$document', function($document) {
  var openScope = null;

  this.open = function( dropdownScope ) {
    if ( !openScope ) {
      $document.bind('click', closeDropdown);
      $document.bind('keydown', escapeKeyBind);
    }

    if ( openScope && openScope !== dropdownScope ) {
        openScope.isOpen = false;
    }

    openScope = dropdownScope;
  };

  this.close = function( dropdownScope ) {
    if ( openScope === dropdownScope ) {
      openScope = null;
      $document.unbind('click', closeDropdown);
      $document.unbind('keydown', escapeKeyBind);
    }
  };

  var closeDropdown = function( evt ) {
    // This method may still be called during the same mouse event that
    // unbound this event handler. So check openScope before proceeding.
    if (!openScope) { return; }

    var toggleElement = openScope.getToggleElement();
    if ( evt && toggleElement && toggleElement[0].contains(evt.target) ) {
        return;
    }

    openScope.$apply(function() {
      openScope.isOpen = false;
    });
  };

  var escapeKeyBind = function( evt ) {
    if ( evt.which === 27 ) {
      openScope.focusToggleElement();
      closeDropdown();
    }
  };
}])

.controller('DropdownController', ['$scope', '$attrs', '$parse', 'dropdownConfig', 'dropdownService', '$animate', function($scope, $attrs, $parse, dropdownConfig, dropdownService, $animate) {
  var self = this,
      scope = $scope.$new(), // create a child scope so we are not polluting original one
      openClass = dropdownConfig.openClass,
      getIsOpen,
      setIsOpen = angular.noop,
      toggleInvoker = $attrs.onToggle ? $parse($attrs.onToggle) : angular.noop;

  this.init = function( element ) {
    self.$element = element;

    if ( $attrs.isOpen ) {
      getIsOpen = $parse($attrs.isOpen);
      setIsOpen = getIsOpen.assign;

      $scope.$watch(getIsOpen, function(value) {
        scope.isOpen = !!value;
      });
    }
  };

  this.toggle = function( open ) {
    return scope.isOpen = arguments.length ? !!open : !scope.isOpen;
  };

  // Allow other directives to watch status
  this.isOpen = function() {
    return scope.isOpen;
  };

  scope.getToggleElement = function() {
    return self.toggleElement;
  };

  scope.focusToggleElement = function() {
    if ( self.toggleElement ) {
      self.toggleElement[0].focus();
    }
  };

  scope.$watch('isOpen', function( isOpen, wasOpen ) {
    $animate[isOpen ? 'addClass' : 'removeClass'](self.$element, openClass);

    if ( isOpen ) {
      scope.focusToggleElement();
      dropdownService.open( scope );
    } else {
      dropdownService.close( scope );
    }

    setIsOpen($scope, isOpen);
    if (angular.isDefined(isOpen) && isOpen !== wasOpen) {
      toggleInvoker($scope, { open: !!isOpen });
    }
  });

  $scope.$on('$locationChangeSuccess', function() {
    scope.isOpen = false;
  });

  $scope.$on('$destroy', function() {
    scope.$destroy();
  });
}])

.directive('dropdown', function() {
  return {
    controller: 'DropdownController',
    link: function(scope, element, attrs, dropdownCtrl) {
      dropdownCtrl.init( element );
    }
  };
})

.directive('dropdownToggle', function() {
  return {
    require: '?^dropdown',
    link: function(scope, element, attrs, dropdownCtrl) {
      if ( !dropdownCtrl ) {
        return;
      }

      dropdownCtrl.toggleElement = element;

      var toggleDropdown = function(event) {
        event.preventDefault();

        if ( !element.hasClass('disabled') && !attrs.disabled ) {
          scope.$apply(function() {
            dropdownCtrl.toggle();
          });
        }
      };

      element.bind('click', toggleDropdown);

      // WAI-ARIA
      element.attr({ 'aria-haspopup': true, 'aria-expanded': false });
      scope.$watch(dropdownCtrl.isOpen, function( isOpen ) {
        element.attr('aria-expanded', !!isOpen);
      });

      scope.$on('$destroy', function() {
        element.unbind('click', toggleDropdown);
      });
    }
  };
});

angular.module('ui.bootstrap.modal', ['ui.bootstrap.transition'])

/**
 * 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 = [];

        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;
          }
        };
      }
    };
  })

/**
 * A helper directive for the $modal service. It creates a backdrop element.
 */
  .directive('modalBackdrop', ['$timeout', function ($timeout) {
    return {
      restrict: 'EA',
      replace: true,
      templateUrl: 'template/modal/backdrop.html',
      link: function (scope, element, attrs) {
        scope.backdropClass = attrs.backdropClass || '';

        scope.animate = false;

        //trigger CSS transitions
        $timeout(function () {
          scope.animate = true;
        });
      }
    };
  }])

  .directive('modalWindow', ['$modalStack', '$timeout', function ($modalStack, $timeout) {
    return {
      restrict: 'EA',
      scope: {
        index: '@',
        animate: '='
      },
      replace: true,
      transclude: true,
      templateUrl: function(tElement, tAttrs) {
        return tAttrs.templateUrl || 'template/modal/window.html';
      },
      link: function (scope, element, attrs) {
        element.addClass(attrs.windowClass || '');
        scope.size = attrs.size;

        $timeout(function () {
          // trigger CSS transitions
          scope.animate = true;

          /**
           * Auto-focusing of a freshly-opened modal element causes any child elements
           * with the autofocus attribute to lose focus. This is an issue on touch
           * based devices which will show and then hide the onscreen keyboard.
           * Attempts to refocus the autofocus element via JavaScript will not reopen
           * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus
           * the modal element if the modal does not contain an autofocus element.
           */
          if (!element[0].querySelectorAll('[autofocus]').length) {
            element[0].focus();
          }
        });

        scope.close = function (evt) {
          var modal = $modalStack.getTop();
          if (modal && modal.value.backdrop && modal.value.backdrop != 'static' && (evt.target === evt.currentTarget)) {
            evt.preventDefault();
            evt.stopPropagation();
            $modalStack.dismiss(modal.key, 'backdrop click');
          }
        };
      }
    };
  }])

  .directive('modalTransclude', function () {
    return {
      link: function($scope, $element, $attrs, controller, $transclude) {
        $transclude($scope.$parent, function(clone) {
          $element.empty();
          $element.append(clone);
        });
      }
    };
  })

  .factory('$modalStack', ['$transition', '$timeout', '$document', '$compile', '$rootScope', '$$stackedMap',
    function ($transition, $timeout, $document, $compile, $rootScope, $$stackedMap) {

      var OPENED_MODAL_CLASS = 'modal-open';

      var backdropDomEl, backdropScope;
      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){
        if (backdropScope) {
          backdropScope.index = newBackdropIndex;
        }
      });

      function removeModalWindow(modalInstance) {

        var body = $document.find('body').eq(0);
        var modalWindow = openedWindows.get(modalInstance).value;

        //clean up the stack
        openedWindows.remove(modalInstance);

        //remove window DOM element
        removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, 300, function() {
          modalWindow.modalScope.$destroy();
          body.toggleClass(OPENED_MODAL_CLASS, openedWindows.length() > 0);
          checkRemoveBackdrop();
        });
      }

      function checkRemoveBackdrop() {
          //remove backdrop if no longer needed
          if (backdropDomEl && backdropIndex() == -1) {
            var backdropScopeRef = backdropScope;
            removeAfterAnimate(backdropDomEl, backdropScope, 150, function () {
              backdropScopeRef.$destroy();
              backdropScopeRef = null;
            });
            backdropDomEl = undefined;
            backdropScope = undefined;
          }
      }

      function removeAfterAnimate(domEl, scope, emulateTime, done) {
        // Closing animation
        scope.animate = false;

        var transitionEndEventName = $transition.transitionEndEventName;
        if (transitionEndEventName) {
          // transition out
          var timeout = $timeout(afterAnimating, emulateTime);

          domEl.bind(transitionEndEventName, function () {
            $timeout.cancel(timeout);
            afterAnimating();
            scope.$apply();
          });
        } else {
          // Ensure this call is async
          $timeout(afterAnimating);
        }

        function afterAnimating() {
          if (afterAnimating.done) {
            return;
          }
          afterAnimating.done = true;

          domEl.remove();
          if (done) {
            done();
          }
        }
      }

      $document.bind('keydown', function (evt) {
        var modal;

        if (evt.which === 27) {
          modal = openedWindows.top();
          if (modal && modal.value.keyboard) {
            evt.preventDefault();
            $rootScope.$apply(function () {
              $modalStack.dismiss(modal.key, 'escape key press');
            });
          }
        }
      });

      $modalStack.open = function (modalInstance, modal) {

        openedWindows.add(modalInstance, {
          deferred: modal.deferred,
          modalScope: modal.scope,
          backdrop: modal.backdrop,
          keyboard: modal.keyboard,
          container: modal.container
        });

        var body = $document.find('body').eq(0);
        var container = modal.container,
            currBackdropIndex = backdropIndex();

        if (currBackdropIndex >= 0 && !backdropDomEl) {
          backdropScope = $rootScope.$new(true);
          backdropScope.index = currBackdropIndex;
          var angularBackgroundDomEl = angular.element('<div modal-backdrop></div>');
          angularBackgroundDomEl.attr('backdrop-class', modal.backdropClass);
          backdropDomEl = $compile(angularBackgroundDomEl)(backdropScope);
          container.append(backdropDomEl);
        }

        var angularDomEl = angular.element('<div modal-window></div>');
        angularDomEl.attr({
          'template-url': modal.windowTemplateUrl,
          'window-class': modal.windowClass,
          'size': modal.size,
          'index': openedWindows.length() - 1,
          'animate': 'animate'
        }).html(modal.content);

        var modalDomEl = $compile(angularDomEl)(modal.scope);
        openedWindows.top().value.modalDomEl = modalDomEl;
        container.append(modalDomEl);
        body.addClass(OPENED_MODAL_CLASS);
      };

      $modalStack.close = function (modalInstance, result) {
        var modalWindow = openedWindows.get(modalInstance);
        if (modalWindow) {
          modalWindow.value.deferred.resolve(result);
          removeModalWindow(modalInstance);
        }
      };

      $modalStack.dismiss = function (modalInstance, reason) {
        var modalWindow = openedWindows.get(modalInstance);
        if (modalWindow) {
          modalWindow.value.deferred.reject(reason);
          removeModalWindow(modalInstance);
        }
      };

      $modalStack.dismissAll = function (reason) {
        var topModal = this.getTop();
        while (topModal) {
          this.dismiss(topModal.key, reason);
          topModal = this.getTop();
        }
      };

      $modalStack.getTop = function () {
        return openedWindows.top();
      };

      return $modalStack;
    }])

  .provider('$modal', function () {

    var $modalProvider = {
      options: {
        backdrop: true, //can be also false or 'static'
        keyboard: true
      },
      defaultContainer: angular.element(document).find('body').eq(0),
      $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(angular.isFunction(options.templateUrl) ? (options.templateUrl)() : options.templateUrl,
                {cache: $templateCache}).then(function (result) {
                  return result.data;
              });
          }

          function getResolvePromises(resolves) {
            var promisesArr = [];
            angular.forEach(resolves, function (value) {
              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);
                if (modalOptions.controllerAs) {
                  modalScope[modalOptions.controllerAs] = ctrlInstance;
                }
              }

              $modalStack.open(modalInstance, {
                scope: modalScope,
                deferred: modalResultDeferred,
                content: tplAndVars[0],
                backdrop: modalOptions.backdrop,
                keyboard: modalOptions.keyboard,
                backdropClass: modalOptions.backdropClass,
                windowClass: modalOptions.windowClass,
                windowTemplateUrl: modalOptions.windowTemplateUrl,
                container: $modalProvider.defaultContainer,
                size: modalOptions.size
              });

            }, 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', '$attrs', '$parse', function ($scope, $attrs, $parse) {
  var self = this,
      ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
      setNumPages = $attrs.numPages ? $parse($attrs.numPages).assign : angular.noop;

  this.init = function(ngModelCtrl_, config) {
    ngModelCtrl = ngModelCtrl_;
    this.config = config;

    ngModelCtrl.$render = function() {
      self.render();
    };

    if ($attrs.itemsPerPage) {
      $scope.$parent.$watch($parse($attrs.itemsPerPage), function(value) {
        self.itemsPerPage = parseInt(value, 10);
        $scope.totalPages = self.calculateTotalPages();
      });
    } else {
      this.itemsPerPage = config.itemsPerPage;
    }
  };

  this.calculateTotalPages = function() {
    var totalPages = this.itemsPerPage < 1 ? 1 : Math.ceil($scope.totalItems / this.itemsPerPage);
    return Math.max(totalPages || 0, 1);
  };

  this.render = function() {
    $scope.page = parseInt(ngModelCtrl.$viewValue, 10) || 1;
  };

  $scope.selectPage = function(page) {
    if ( $scope.page !== page && page > 0 && page <= $scope.totalPages) {
      ngModelCtrl.$setViewValue(page);
      ngModelCtrl.$render();
    }
  };

  $scope.getText = function( key ) {
    return $scope[key + 'Text'] || self.config[key + 'Text'];
  };
  $scope.noPrevious = function() {
    return $scope.page === 1;
  };
  $scope.noNext = function() {
    return $scope.page === $scope.totalPages;
  };

  $scope.$watch('totalItems', function() {
    $scope.totalPages = self.calculateTotalPages();
  });

  $scope.$watch('totalPages', function(value) {
    setNumPages($scope.$parent, value); // Readonly variable

    if ( $scope.page > value ) {
      $scope.selectPage(value);
    } else {
      ngModelCtrl.$render();
    }
  });
}])

.constant('paginationConfig', {
  itemsPerPage: 10,
  boundaryLinks: false,
  directionLinks: true,
  firstText: 'First',
  previousText: 'Previous',
  nextText: 'Next',
  lastText: 'Last',
  rotate: true
})

.directive('pagination', ['$parse', 'paginationConfig', function($parse, paginationConfig) {
  return {
    restrict: 'EA',
    scope: {
      totalItems: '=',
      firstText: '@',
      previousText: '@',
      nextText: '@',
      lastText: '@'
    },
    require: ['pagination', '?ngModel'],
    controller: 'PaginationController',
    templateUrl: 'template/pagination/pagination.html',
    replace: true,
    link: function(scope, element, attrs, ctrls) {
      var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];

      if (!ngModelCtrl) {
         return; // do nothing if no ng-model
      }

      // Setup configuration parameters
      var maxSize = angular.isDefined(attrs.maxSize) ? scope.$parent.$eval(attrs.maxSize) : paginationConfig.maxSize,
          rotate = angular.isDefined(attrs.rotate) ? scope.$parent.$eval(attrs.rotate) : paginationConfig.rotate;
      scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : paginationConfig.boundaryLinks;
      scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : paginationConfig.directionLinks;

      paginationCtrl.init(ngModelCtrl, paginationConfig);

      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) {
        return {
          number: number,
          text: text,
          active: isActive
        };
      }

      function getPages(currentPage, totalPages) {
        var pages = [];

        // Default page limits
        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(currentPage - Math.floor(maxSize/2), 1);
            endPage   = startPage + maxSize - 1;

            // Adjust if limit is exceeded
            if (endPage > totalPages) {
              endPage   = totalPages;
              startPage = endPage - maxSize + 1;
            }
          } else {
            // Visible pages are paginated with maxSize
            startPage = ((Math.ceil(currentPage / maxSize) - 1) * maxSize) + 1;

            // Adjust last page if limit is exceeded
            endPage = Math.min(startPage + maxSize - 1, totalPages);
          }
        }

        // Add page number links
        for (var number = startPage; number <= endPage; number++) {
          var page = makePage(number, number, number === currentPage);
          pages.push(page);
        }

        // Add links to move between page sets
        if ( isMaxSized && ! rotate ) {
          if ( startPage > 1 ) {
            var previousPageSet = makePage(startPage - 1, '...', false);
            pages.unshift(previousPageSet);
          }

          if ( endPage < totalPages ) {
            var nextPageSet = makePage(endPage + 1, '...', false);
            pages.push(nextPageSet);
          }
        }

        return pages;
      }

      var originalRender = paginationCtrl.render;
      paginationCtrl.render = function() {
        originalRender();
        if (scope.page > 0 && scope.page <= scope.totalPages) {
          scope.pages = getPages(scope.page, scope.totalPages);
        }
      };
    }
  };
}])

.constant('pagerConfig', {
  itemsPerPage: 10,
  previousText: '« Previous',
  nextText: 'Next »',
  align: true
})

.directive('pager', ['pagerConfig', function(pagerConfig) {
  return {
    restrict: 'EA',
    scope: {
      totalItems: '=',
      previousText: '@',
      nextText: '@'
    },
    require: ['pager', '?ngModel'],
    controller: 'PaginationController',
    templateUrl: 'template/pagination/pager.html',
    replace: true,
    link: function(scope, element, attrs, ctrls) {
      var paginationCtrl = ctrls[0], ngModelCtrl = ctrls[1];

      if (!ngModelCtrl) {
         return; // do nothing if no ng-model
      }

      scope.align = angular.isDefined(attrs.align) ? scope.$parent.$eval(attrs.align) : pagerConfig.align;
      paginationCtrl.init(ngModelCtrl, pagerConfig);
    }
  };
}]);

/**
 * The following features are still outstanding: animation as a
 * 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', 'ui.bootstrap.bindHtml' ] )

/**
 * The $tooltip service creates tooltip- and popover-like directives as well as
 * houses global options for them.
 */
.provider( '$tooltip', function () {
  // The default options tooltip and popover.
  var defaultOptions = {
    placement: 'top',
    animation: true,
    popupDelay: 0
  };

  // Default hide triggers for each show trigger
  var triggerMap = {
    'mouseenter': 'mouseleave',
    'click': 'click',
    'focus': 'blur'
  };

  // The options specified to the provider globally.
  var globalOptions = {};

  /**
   * `options({})` allows global configuration of all tooltips in the
   * application.
   *
   *   var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {
   *     // place tooltips left instead of top by default
   *     $tooltipProvider.options( { placement: 'left' } );
   *   });
   */
	this.options = function( value ) {
		angular.extend( globalOptions, value );
	};

  /**
   * This allows you to extend the set of trigger mappings available. E.g.:
   *
   *   $tooltipProvider.setTriggers( 'openTrigger': 'closeTrigger' );
   */
  this.setTriggers = function setTriggers ( triggers ) {
    angular.extend( triggerMap, triggers );
  };

  /**
   * This is a helper function for translating camel-case to snake-case.
   */
  function snake_case(name){
    var regexp = /[A-Z]/g;
    var separator = '-';
    return name.replace(regexp, function(letter, pos) {
      return (pos ? separator : '') + letter.toLowerCase();
    });
  }

  /**
   * Returns the actual instance of the $tooltip service.
   * TODO support multiple triggers
   */
  this.$get = [ '$window', '$compile', '$timeout', '$document', '$position', '$interpolate', function ( $window, $compile, $timeout, $document, $position, $interpolate ) {
    return function $tooltip ( type, prefix, defaultTriggerShow ) {
      var options = angular.extend( {}, defaultOptions, globalOptions );

      /**
       * Returns an object of show and hide triggers.
       *
       * If a trigger is supplied,
       * it is used to show the tooltip; otherwise, it will use the `trigger`
       * option passed to the `$tooltipProvider.options` method; else it will
       * default to the trigger supplied to this directive factory.
       *
       * The hide trigger is based on the show trigger. If the `trigger` option
       * was passed to the `$tooltipProvider.options` method, it will use the
       * mapped trigger from `triggerMap` or the passed trigger if the map is
       * undefined; otherwise, it uses the `triggerMap` value of the show
       * trigger; else it will just use the show trigger.
       */
      function getTriggers ( trigger ) {
        var show = trigger || options.trigger || defaultTriggerShow;
        var hide = triggerMap[show] || show;
        return {
          show: show,
          hide: hide
        };
      }

      var directiveName = snake_case( type );

      var startSym = $interpolate.startSymbol();
      var endSym = $interpolate.endSymbol();
      var template =
        '<div '+ directiveName +'-popup '+
          'title="'+startSym+'title'+endSym+'" '+
          'content="'+startSym+'content'+endSym+'" '+
          'placement="'+startSym+'placement'+endSym+'" '+
          'animation="animation" '+
          'is-open="isOpen"'+
          '>'+
        '</div>';

      return {
        restrict: 'EA',
        compile: function (tElem, tAttrs) {
          var tooltipLinker = $compile( template );

          return function link ( scope, element, attrs ) {
            var tooltip;
            var tooltipLinkedScope;
            var transitionTimeout;
            var popupTimeout;
            var appendToBody = angular.isDefined( options.appendToBody ) ? options.appendToBody : false;
            var triggers = getTriggers( undefined );
            var hasEnableExp = angular.isDefined(attrs[prefix+'Enable']);
            var ttScope = scope.$new(true);

            var positionTooltip = function () {

              var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);
              ttPosition.top += 'px';
              ttPosition.left += 'px';

              // Now set the calculated positioning.
              tooltip.css( ttPosition );
            };

            // By default, the tooltip is not open.
            // TODO add ability to start tooltip opened
            ttScope.isOpen = false;

            function toggleTooltipBind () {
              if ( ! ttScope.isOpen ) {
                showTooltipBind();
              } else {
                hideTooltipBind();
              }
            }

            // Show the tooltip with delay if specified, otherwise show it immediately
            function showTooltipBind() {
              if(hasEnableExp && !scope.$eval(attrs[prefix+'Enable'])) {
                return;
              }

              prepareTooltip();

              if ( ttScope.popupDelay ) {
                // Do nothing if the tooltip was already scheduled to pop-up.
                // This happens if show is triggered multiple times before any hide is triggered.
                if (!popupTimeout) {
                  popupTimeout = $timeout( show, ttScope.popupDelay, false );
                  popupTimeout.then(function(reposition){reposition();});
                }
              } else {
                show()();
              }
            }

            function hideTooltipBind () {
              scope.$apply(function () {
                hide();
              });
            }

            // Show the tooltip popup element.
            function show() {

              popupTimeout = null;

              // If there is a pending remove transition, we must cancel it, lest the
              // tooltip be mysteriously removed.
              if ( transitionTimeout ) {
                $timeout.cancel( transitionTimeout );
                transitionTimeout = null;
              }

              // Don't show empty tooltips.
              if ( ! ttScope.content ) {
                return angular.noop;
              }

              createTooltip();

              // Set the initial positioning.
              tooltip.css({ top: 0, left: 0, display: 'block' });
              ttScope.$digest();

              positionTooltip();

              // And show the tooltip.
              ttScope.isOpen = true;
              ttScope.$digest(); // digest required as $apply is not called

              // Return positioning function as promise callback for correct
              // positioning after draw.
              return positionTooltip;
            }

            // Hide the tooltip popup element.
            function hide() {
              // First things first: we don't show it anymore.
              ttScope.isOpen = false;

              //if tooltip is going to be shown after delay, we must cancel this
              $timeout.cancel( popupTimeout );
              popupTimeout = null;

              // And now we remove it from the DOM. However, if we have animation, we
              // need to wait for it to expire beforehand.
              // FIXME: this is a placeholder for a port of the transitions library.
              if ( ttScope.animation ) {
                if (!transitionTimeout) {
                  transitionTimeout = $timeout(removeTooltip, 500);
                }
              } else {
                removeTooltip();
              }
            }

            function createTooltip() {
              // There can only be one tooltip element per directive shown at once.
              if (tooltip) {
                removeTooltip();
              }
              tooltipLinkedScope = ttScope.$new();
              tooltip = tooltipLinker(tooltipLinkedScope, function (tooltip) {
                if ( appendToBody ) {
                  $document.find( 'body' ).append( tooltip );
                } else {
                  element.after( tooltip );
                }
              });
            }

            function removeTooltip() {
              transitionTimeout = null;
              if (tooltip) {
                tooltip.remove();
                tooltip = null;
              }
              if (tooltipLinkedScope) {
                tooltipLinkedScope.$destroy();
                tooltipLinkedScope = null;
              }
            }

            function prepareTooltip() {
              prepPlacement();
              prepPopupDelay();
            }

            /**
             * Observe the relevant attributes.
             */
            attrs.$observe( type, function ( val ) {
              ttScope.content = val;

              if (!val && ttScope.isOpen ) {
                hide();
              }
            });

            attrs.$observe( prefix+'Title', function ( val ) {
              ttScope.title = val;
            });

            function prepPlacement() {
              var val = attrs[ prefix + 'Placement' ];
              ttScope.placement = angular.isDefined( val ) ? val : options.placement;
            }

            function prepPopupDelay() {
              var val = attrs[ prefix + 'PopupDelay' ];
              var delay = parseInt( val, 10 );
              ttScope.popupDelay = ! isNaN(delay) ? delay : options.popupDelay;
            }

            var unregisterTriggers = function () {
              element.unbind(triggers.show, showTooltipBind);
              element.unbind(triggers.hide, hideTooltipBind);
            };

            function prepTriggers() {
              var val = attrs[ prefix + 'Trigger' ];
              unregisterTriggers();

              triggers = getTriggers( val );

              if ( triggers.show === triggers.hide ) {
                element.bind( triggers.show, toggleTooltipBind );
              } else {
                element.bind( triggers.show, showTooltipBind );
                element.bind( triggers.hide, hideTooltipBind );
              }
            }
            prepTriggers();

            var animation = scope.$eval(attrs[prefix + 'Animation']);
            ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;

            var appendToBodyVal = scope.$eval(attrs[prefix + 'AppendToBody']);
            appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;

            // if a tooltip is attached to <body> we need to remove it on
            // location change as its parent scope will probably not be destroyed
            // by the change.
            if ( appendToBody ) {
              scope.$on('$locationChangeSuccess', function closeTooltipOnLocationChangeSuccess () {
              if ( ttScope.isOpen ) {
                hide();
              }
            });
            }

            // Make sure tooltip is destroyed and removed.
            scope.$on('$destroy', function onDestroyTooltip() {
              $timeout.cancel( transitionTimeout );
              $timeout.cancel( popupTimeout );
              unregisterTriggers();
              removeTooltip();
              ttScope = null;
            });
          };
        }
      };
    };
  }];
})

.directive( 'tooltipPopup', function () {
  return {
    restrict: 'EA',
    replace: true,
    scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
    templateUrl: 'template/tooltip/tooltip-popup.html'
  };
})

.directive( 'tooltip', [ '$tooltip', function ( $tooltip ) {
  return $tooltip( 'tooltip', 'tooltip', 'mouseenter' );
}])

.directive( 'tooltipHtmlUnsafePopup', function () {
  return {
    restrict: 'EA',
    replace: true,
    scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
    templateUrl: 'template/tooltip/tooltip-html-unsafe-popup.html'
  };
})

.directive( 'tooltipHtmlUnsafe', [ '$tooltip', function ( $tooltip ) {
  return $tooltip( 'tooltipHtmlUnsafe', 'tooltip', 'mouseenter' );
}]);

/**
 * The following features are still outstanding: popup delay, animation as a
 * function, placement as a function, inside, support for more triggers than
 * just mouse enter/leave, html popovers, and selector delegatation.
 */
angular.module( 'ui.bootstrap.popover', [ 'ui.bootstrap.tooltip' ] )

.directive( 'popoverPopup', function () {
  return {
    restrict: 'EA',
    replace: true,
    scope: { title: '@', content: '@', placement: '@', animation: '&', isOpen: '&' },
    templateUrl: 'template/popover/popover.html'
  };
})

.directive( 'popover', [ '$tooltip', function ( $tooltip ) {
  return $tooltip( 'popover', 'popover', 'click' );
}]);

angular.module('ui.bootstrap.progressbar', [])

.constant('progressConfig', {
  animate: true,
  max: 100
})

.controller('ProgressController', ['$scope', '$attrs', 'progressConfig', function($scope, $attrs, progressConfig) {
    var self = this,
        animate = angular.isDefined($attrs.animate) ? $scope.$parent.$eval($attrs.animate) : progressConfig.animate;

    this.bars = [];
    $scope.max = angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : progressConfig.max;

    this.addBar = function(bar, element) {
        if ( !animate ) {
            element.css({'transition': 'none'});
        }

        this.bars.push(bar);

        bar.$watch('value', function( value ) {
            bar.percent = +(100 * value / $scope.max).toFixed(2);
        });

        bar.$on('$destroy', function() {
            element = null;
            self.removeBar(bar);
        });
    };

    this.removeBar = function(bar) {
        this.bars.splice(this.bars.indexOf(bar), 1);
    };
}])

.directive('progress', function() {
    return {
        restrict: 'EA',
        replace: true,
        transclude: true,
        controller: 'ProgressController',
        require: 'progress',
        scope: {},
        templateUrl: 'template/progressbar/progress.html'
    };
})

.directive('bar', function() {
    return {
        restrict: 'EA',
        replace: true,
        transclude: true,
        require: '^progress',
        scope: {
            value: '=',
            type: '@'
        },
        templateUrl: 'template/progressbar/bar.html',
        link: function(scope, element, attrs, progressCtrl) {
            progressCtrl.addBar(scope, element);
        }
    };
})

.directive('progressbar', function() {
    return {
        restrict: 'EA',
        replace: true,
        transclude: true,
        controller: 'ProgressController',
        scope: {
            value: '=',
            type: '@'
        },
        templateUrl: 'template/progressbar/progressbar.html',
        link: function(scope, element, attrs, progressCtrl) {
            progressCtrl.addBar(scope, angular.element(element.children()[0]));
        }
    };
});
angular.module('ui.bootstrap.rating', [])

.constant('ratingConfig', {
  max: 5,
  stateOn: null,
  stateOff: null
})

.controller('RatingController', ['$scope', '$attrs', 'ratingConfig', function($scope, $attrs, ratingConfig) {
  var ngModelCtrl  = { $setViewValue: angular.noop };

  this.init = function(ngModelCtrl_) {
    ngModelCtrl = ngModelCtrl_;
    ngModelCtrl.$render = this.render;

    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;

    var ratingStates = angular.isDefined($attrs.ratingStates) ? $scope.$parent.$eval($attrs.ratingStates) :
                        new Array( angular.isDefined($attrs.max) ? $scope.$parent.$eval($attrs.max) : ratingConfig.max );
    $scope.range = this.buildTemplateObjects(ratingStates);
  };

  this.buildTemplateObjects = function(states) {
    for (var i = 0, n = states.length; i < n; i++) {
      states[i] = angular.extend({ index: i }, { stateOn: this.stateOn, stateOff: this.stateOff }, states[i]);
    }
    return states;
  };

  $scope.rate = function(value) {
    if ( !$scope.readonly && value >= 0 && value <= $scope.range.length ) {
      ngModelCtrl.$setViewValue(value);
      ngModelCtrl.$render();
    }
  };

  $scope.enter = function(value) {
    if ( !$scope.readonly ) {
      $scope.value = value;
    }
    $scope.onHover({value: value});
  };

  $scope.reset = function() {
    $scope.value = ngModelCtrl.$viewValue;
    $scope.onLeave();
  };

  $scope.onKeydown = function(evt) {
    if (/(37|38|39|40)/.test(evt.which)) {
      evt.preventDefault();
      evt.stopPropagation();
      $scope.rate( $scope.value + (evt.which === 38 || evt.which === 39 ? 1 : -1) );
    }
  };

  this.render = function() {
    $scope.value = ngModelCtrl.$viewValue;
  };
}])

.directive('rating', function() {
  return {
    restrict: 'EA',
    require: ['rating', 'ngModel'],
    scope: {
      readonly: '=?',
      onHover: '&',
      onLeave: '&'
    },
    controller: 'RatingController',
    templateUrl: 'template/rating/rating.html',
    replace: true,
    link: function(scope, element, attrs, ctrls) {
      var ratingCtrl = ctrls[0], ngModelCtrl = ctrls[1];

      if ( ngModelCtrl ) {
        ratingCtrl.init( ngModelCtrl );
      }
    }
  };
});

/**
 * @ngdoc overview
 * @name ui.bootstrap.tabs
 *
 * @description
 * AngularJS version of the tabs directive.
 */

angular.module('ui.bootstrap.tabs', [])

.controller('TabsetController', ['$scope', function TabsetCtrl($scope) {
  var ctrl = this,
      tabs = ctrl.tabs = $scope.tabs = [];

  ctrl.select = function(selectedTab) {
    angular.forEach(tabs, function(tab) {
      if (tab.active && tab !== selectedTab) {
        tab.active = false;
        tab.onDeselect();
      }
    });
    selectedTab.active = true;
    selectedTab.onSelect();
  };

  ctrl.addTab = function addTab(tab) {
    tabs.push(tab);
    // we can't run the select function on the first tab
    // since that would select it twice
    if (tabs.length === 1) {
      tab.active = true;
    } else if (tab.active) {
      ctrl.select(tab);
    }
  };

  ctrl.removeTab = function removeTab(tab) {
    var index = tabs.indexOf(tab);
    //Select a new tab if the tab to be removed is selected and not destroyed
    if (tab.active && tabs.length > 1 && !destroyed) {
      //If this is the last tab, select the previous tab. else, the next tab.
      var newActiveIndex = index == tabs.length - 1 ? index - 1 : index + 1;
      ctrl.select(tabs[newActiveIndex]);
    }
    tabs.splice(index, 1);
  };

  var destroyed;
  $scope.$on('$destroy', function() {
    destroyed = true;
  });
}])

/**
 * @ngdoc directive
 * @name ui.bootstrap.tabs.directive:tabset
 * @restrict EA
 *
 * @description
 * Tabset is the outer container for the tabs directive
 *
 * @param {boolean=} vertical Whether or not to use vertical styling for the tabs.
 * @param {boolean=} justified Whether or not to use justified styling for the tabs.
 *
 * @example
<example module="ui.bootstrap">
  <file name="index.html">
    <tabset>
      <tab heading="Tab 1"><b>First</b> Content!</tab>
      <tab heading="Tab 2"><i>Second</i> Content!</tab>
    </tabset>
    <hr />
    <tabset vertical="true">
      <tab heading="Vertical Tab 1"><b>First</b> Vertical Content!</tab>
      <tab heading="Vertical Tab 2"><i>Second</i> Vertical Content!</tab>
    </tabset>
    <tabset justified="true">
      <tab heading="Justified Tab 1"><b>First</b> Justified Content!</tab>
      <tab heading="Justified Tab 2"><i>Second</i> Justified Content!</tab>
    </tabset>
  </file>
</example>
 */
.directive('tabset', function() {
  return {
    restrict: 'EA',
    transclude: true,
    replace: true,
    scope: {
      type: '@'
    },
    controller: 'TabsetController',
    templateUrl: 'template/tabs/tabset.html',
    link: function(scope, element, attrs) {
      scope.vertical = angular.isDefined(attrs.vertical) ? scope.$parent.$eval(attrs.vertical) : false;
      scope.justified = angular.isDefined(attrs.justified) ? scope.$parent.$eval(attrs.justified) : false;
    }
  };
})

/**
 * @ngdoc directive
 * @name ui.bootstrap.tabs.directive:tab
 * @restrict EA
 *
 * @param {string=} heading The visible heading, or title, of the tab. Set HTML headings with {@link ui.bootstrap.tabs.directive:tabHeading tabHeading}.
 * @param {string=} select An expression to evaluate when the tab is selected.
 * @param {boolean=} active A binding, telling whether or not this tab is selected.
 * @param {boolean=} disabled A binding, telling whether or not this tab is disabled.
 *
 * @description
 * Creates a tab with a heading and content. Must be placed within a {@link ui.bootstrap.tabs.directive:tabset tabset}.
 *
 * @example
<example module="ui.bootstrap">
  <file name="index.html">
    <div ng-controller="TabsDemoCtrl">
      <button class="btn btn-small" ng-click="items[0].active = true">
        Select item 1, using active binding
      </button>
      <button class="btn btn-small" ng-click="items[1].disabled = !items[1].disabled">
        Enable/disable item 2, using disabled binding
      </button>
      <br />
      <tabset>
        <tab heading="Tab 1">First Tab</tab>
        <tab select="alertMe()">
          <tab-heading><i class="icon-bell"></i> Alert me!</tab-heading>
          Second Tab, with alert callback and html heading!
        </tab>
        <tab ng-repeat="item in items"
          heading="{{item.title}}"
          disabled="item.disabled"
          active="item.active">
          {{item.content}}
        </tab>
      </tabset>
    </div>
  </file>
  <file name="script.js">
    function TabsDemoCtrl($scope) {
      $scope.items = [
        { title:"Dynamic Title 1", content:"Dynamic Item 0" },
        { title:"Dynamic Title 2", content:"Dynamic Item 1", disabled: true }
      ];

      $scope.alertMe = function() {
        setTimeout(function() {
          alert("You've selected the alert tab!");
        });
      };
    };
  </file>
</example>
 */

/**
 * @ngdoc directive
 * @name ui.bootstrap.tabs.directive:tabHeading
 * @restrict EA
 *
 * @description
 * Creates an HTML heading for a {@link ui.bootstrap.tabs.directive:tab tab}. Must be placed as a child of a tab element.
 *
 * @example
<example module="ui.bootstrap">
  <file name="index.html">
    <tabset>
      <tab>
        <tab-heading><b>HTML</b> in my titles?!</tab-heading>
        And some content, too!
      </tab>
      <tab>
        <tab-heading><i class="icon-heart"></i> Icon heading?!?</tab-heading>
        That's right.
      </tab>
    </tabset>
  </file>
</example>
 */
.directive('tab', ['$parse', function($parse) {
  return {
    require: '^tabset',
    restrict: 'EA',
    replace: true,
    templateUrl: 'template/tabs/tab.html',
    transclude: true,
    scope: {
      active: '=?',
      heading: '@',
      onSelect: '&select', //This callback is called in contentHeadingTransclude
                          //once it inserts the tab's content into the dom
      onDeselect: '&deselect'
    },
    controller: function() {
      //Empty controller so other directives can require being 'under' a tab
    },
    compile: function(elm, attrs, transclude) {
      return function postLink(scope, elm, attrs, tabsetCtrl) {
        scope.$watch('active', function(active) {
          if (active) {
            tabsetCtrl.select(scope);
          }
        });

        scope.disabled = false;
        if ( attrs.disabled ) {
          scope.$parent.$watch($parse(attrs.disabled), function(value) {
            scope.disabled = !! value;
          });
        }

        scope.select = function() {
          if ( !scope.disabled ) {
            scope.active = true;
          }
        };

        tabsetCtrl.addTab(scope);
        scope.$on('$destroy', function() {
          tabsetCtrl.removeTab(scope);
        });

        //We need to transclude later, once the content container is ready.
        //when this link happens, we're inside a tab heading.
        scope.$transcludeFn = transclude;
      };
    }
  };
}])

.directive('tabHeadingTransclude', [function() {
  return {
    restrict: 'A',
    require: '^tab',
    link: function(scope, elm, attrs, tabCtrl) {
      scope.$watch('headingElement', function updateHeadingElement(heading) {
        if (heading) {
          elm.html('');
          elm.append(heading);
        }
      });
    }
  };
}])

.directive('tabContentTransclude', function() {
  return {
    restrict: 'A',
    require: '^tabset',
    link: function(scope, elm, attrs) {
      var tab = scope.$eval(attrs.tabContentTransclude);

      //Now our tab is ready to be transcluded: both the tab heading area
      //and the tab content area are loaded.  Transclude 'em both.
      tab.$transcludeFn(tab.$parent, function(contents) {
        angular.forEach(contents, function(node) {
          if (isTabHeading(node)) {
            //Let tabHeadingTransclude know.
            tab.headingElement = node;
          } else {
            elm.append(node);
          }
        });
      });
    }
  };
  function isTabHeading(node) {
    return node.tagName &&  (
      node.hasAttribute('tab-heading') ||
      node.hasAttribute('data-tab-heading') ||
      node.tagName.toLowerCase() === 'tab-heading' ||
      node.tagName.toLowerCase() === 'data-tab-heading'
    );
  }
})

;

angular.module('ui.bootstrap.timepicker', [])

.constant('timepickerConfig', {
  hourStep: 1,
  minuteStep: 1,
  showMeridian: true,
  meridians: null,
  readonlyInput: false,
  mousewheel: true
})

.controller('TimepickerController', ['$scope', '$attrs', '$parse', '$log', '$locale', 'timepickerConfig', function($scope, $attrs, $parse, $log, $locale, timepickerConfig) {
  var selected = new Date(),
      ngModelCtrl = { $setViewValue: angular.noop }, // nullModelCtrl
      meridians = angular.isDefined($attrs.meridians) ? $scope.$parent.$eval($attrs.meridians) : timepickerConfig.meridians || $locale.DATETIME_FORMATS.AMPMS;

  this.init = function( ngModelCtrl_, inputs ) {
    ngModelCtrl = ngModelCtrl_;
    ngModelCtrl.$render = this.render;

    var hoursInputEl = inputs.eq(0),
        minutesInputEl = inputs.eq(1);

    var mousewheel = angular.isDefined($attrs.mousewheel) ? $scope.$parent.$eval($attrs.mousewheel) : timepickerConfig.mousewheel;
    if ( mousewheel ) {
      this.setupMousewheelEvents( hoursInputEl, minutesInputEl );
    }

    $scope.readonlyInput = angular.isDefined($attrs.readonlyInput) ? $scope.$parent.$eval($attrs.readonlyInput) : timepickerConfig.readonlyInput;
    this.setupInputEvents( hoursInputEl, minutesInputEl );
  };

  var hourStep = timepickerConfig.hourStep;
  if ($attrs.hourStep) {
    $scope.$parent.$watch($parse($attrs.hourStep), function(value) {
      hourStep = parseInt(value, 10);
    });
  }

  var minuteStep = timepickerConfig.minuteStep;
  if ($attrs.minuteStep) {
    $scope.$parent.$watch($parse($attrs.minuteStep), function(value) {
      minuteStep = parseInt(value, 10);
    });
  }

  // 12H / 24H mode
  $scope.showMeridian = timepickerConfig.showMeridian;
  if ($attrs.showMeridian) {
    $scope.$parent.$watch($parse($attrs.showMeridian), function(value) {
      $scope.showMeridian = !!value;

      if ( ngModelCtrl.$error.time ) {
        // Evaluate from template
        var hours = getHoursFromTemplate(), minutes = getMinutesFromTemplate();
        if (angular.isDefined( hours ) && angular.isDefined( minutes )) {
          selected.setHours( hours );
          refresh();
        }
      } else {
        updateTemplate();
      }
    });
  }

  // Get $scope.hours in 24H mode if valid
  function getHoursFromTemplate ( ) {
    var hours = parseInt( $scope.hours, 10 );
    var valid = ( $scope.showMeridian ) ? (hours > 0 && hours < 13) : (hours >= 0 && hours < 24);
    if ( !valid ) {
      return undefined;
    }

    if ( $scope.showMeridian ) {
      if ( hours === 12 ) {
        hours = 0;
      }
      if ( $scope.meridian === meridians[1] ) {
        hours = hours + 12;
      }
    }
    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;
  }

  // Respond on mousewheel spin
  this.setupMousewheelEvents = function( hoursInputEl, minutesInputEl ) {
    var isScrollingUp = function(e) {
      if (e.originalEvent) {
        e = e.originalEvent;
      }
      //pick correct delta variable depending on event
      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();
    });

    minutesInputEl.bind('mousewheel wheel', function(e) {
      $scope.$apply( (isScrollingUp(e)) ? $scope.incrementMinutes() : $scope.decrementMinutes() );
      e.preventDefault();
    });

  };

  this.setupInputEvents = function( hoursInputEl, minutesInputEl ) {
    if ( $scope.readonlyInput ) {
      $scope.updateHours = angular.noop;
      $scope.updateMinutes = angular.noop;
      return;
    }

    var invalidate = function(invalidHours, invalidMinutes) {
      ngModelCtrl.$setViewValue( null );
      ngModelCtrl.$setValidity('time', false);
      if (angular.isDefined(invalidHours)) {
        $scope.invalidHours = invalidHours;
      }
      if (angular.isDefined(invalidMinutes)) {
        $scope.invalidMinutes = invalidMinutes;
      }
    };

    $scope.updateHours = function() {
      var hours = getHoursFromTemplate();

      if ( angular.isDefined(hours) ) {
        selected.setHours( hours );
        refresh( 'h' );
      } else {
        invalidate(true);
      }
    };

    hoursInputEl.bind('blur', function(e) {
      if ( !$scope.invalidHours && $scope.hours < 10) {
        $scope.$apply( function() {
          $scope.hours = pad( $scope.hours );
        });
      }
    });

    $scope.updateMinutes = function() {
      var minutes = getMinutesFromTemplate();

      if ( angular.isDefined(minutes) ) {
        selected.setMinutes( minutes );
        refresh( 'm' );
      } else {
        invalidate(undefined, true);
      }
    };

    minutesInputEl.bind('blur', function(e) {
      if ( !$scope.invalidMinutes && $scope.minutes < 10 ) {
        $scope.$apply( function() {
          $scope.minutes = pad( $scope.minutes );
        });
      }
    });

  };

  this.render = function() {
    var date = ngModelCtrl.$modelValue ? new Date( ngModelCtrl.$modelValue ) : null;

    if ( isNaN(date) ) {
      ngModelCtrl.$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();
    }
  };

  // Call internally when we know that model is valid.
  function refresh( keyboardChange ) {
    makeValid();
    ngModelCtrl.$setViewValue( new Date(selected) );
    updateTemplate( keyboardChange );
  }

  function makeValid() {
    ngModelCtrl.$setValidity('time', true);
    $scope.invalidHours = false;
    $scope.invalidMinutes = false;
  }

  function updateTemplate( keyboardChange ) {
    var hours = selected.getHours(), minutes = selected.getMinutes();

    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(), dt.getMinutes() );
    refresh();
  }

  $scope.incrementHours = function() {
    addMinutes( hourStep * 60 );
  };
  $scope.decrementHours = function() {
    addMinutes( - hourStep * 60 );
  };
  $scope.incrementMinutes = function() {
    addMinutes( minuteStep );
  };
  $scope.decrementMinutes = function() {
    addMinutes( - minuteStep );
  };
  $scope.toggleMeridian = function() {
    addMinutes( 12 * 60 * (( selected.getHours() < 12 ) ? 1 : -1) );
  };
}])

.directive('timepicker', function () {
  return {
    restrict: 'EA',
    require: ['timepicker', '?^ngModel'],
    controller:'TimepickerController',
    replace: true,
    scope: {},
    templateUrl: 'template/timepicker/timepicker.html',
    link: function(scope, element, attrs, ctrls) {
      var timepickerCtrl = ctrls[0], ngModelCtrl = ctrls[1];

      if ( ngModelCtrl ) {
        timepickerCtrl.init( ngModelCtrl, element.find('input') );
      }
    }
  };
});

angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap.bindHtml'])

/**
 * A helper service that can parse typeahead's syntax (string provided by users)
 * Extracted to a separate service for ease of unit testing
 */
  .factory('typeaheadParser', ['$parse', function ($parse) {

  //                      00000111000000000000022200000000000000003333333333333330000000000044000
  var TYPEAHEAD_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;

  return {
    parse:function (input) {

      var match = input.match(TYPEAHEAD_REGEXP);
      if (!match) {
        throw new Error(
          'Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_"' +
            ' but got "' + input + '".');
      }

      return {
        itemName:match[3],
        source:$parse(match[4]),
        viewMapper:$parse(match[2] || match[1]),
        modelMapper:$parse(match[1])
      };
    }
  };
}])

  .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];

  return {
    require:'ngModel',
    link:function (originalScope, element, attrs, modelCtrl) {

      //SUPPORTED ATTRIBUTES (OPTIONS)

      //minimal no of characters that needs to be entered before typeahead kicks-in
      var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1;

      //minimal wait time after last character typed before typehead kicks-in
      var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;

      //should it restrict model values to the ones selected from the popup only?
      var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;

      //binding to a variable that indicates if matches are being retrieved asynchronously
      var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;

      //a callback executed when a match is selected
      var onSelectCallback = $parse(attrs.typeaheadOnSelect);

      var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;

      var appendToBody =  attrs.typeaheadAppendToBody ? originalScope.$eval(attrs.typeaheadAppendToBody) : false;

      var focusFirst = originalScope.$eval(attrs.typeaheadFocusFirst) !== false;

      //INTERNAL VARIABLES

      //model setter executed upon match selection
      var $setModelValue = $parse(attrs.ngModel).assign;

      //expressions used by typeahead
      var parserResult = typeaheadParser.parse(attrs.typeahead);

      var hasFocus;

      //create a child scope for the typeahead directive so we are not polluting original scope
      //with typeahead-specific data (matches, query etc.)
      var scope = originalScope.$new();
      originalScope.$on('$destroy', function(){
        scope.$destroy();
      });

      // WAI-ARIA
      var popupId = 'typeahead-' + scope.$id + '-' + Math.floor(Math.random() * 10000);
      element.attr({
        'aria-autocomplete': 'list',
        'aria-expanded': false,
        'aria-owns': popupId
      });

      //pop-up element used to display matches
      var popUpEl = angular.element('<div typeahead-popup></div>');
      popUpEl.attr({
        id: popupId,
        matches: 'matches',
        active: 'activeIdx',
        select: 'select(activeIdx)',
        query: 'query',
        position: 'position'
      });
      //custom item template
      if (angular.isDefined(attrs.typeaheadTemplateUrl)) {
        popUpEl.attr('template-url', attrs.typeaheadTemplateUrl);
      }

      var resetMatches = function() {
        scope.matches = [];
        scope.activeIdx = -1;
        element.attr('aria-expanded', false);
      };

      var getMatchId = function(index) {
        return popupId + '-option-' + index;
      };

      // Indicate that the specified match is the active (pre-selected) item in the list owned by this typeahead.
      // This attribute is added or removed automatically when the `activeIdx` changes.
      scope.$watch('activeIdx', function(index) {
        if (index < 0) {
          element.removeAttr('aria-activedescendant');
        } else {
          element.attr('aria-activedescendant', getMatchId(index));
        }
      });

      var getMatchesAsync = function(inputValue) {

        var locals = {$viewValue: inputValue};
        isLoadingSetter(originalScope, true);
        $q.when(parserResult.source(originalScope, locals)).then(function(matches) {

          //it might happen that several async queries were in progress if a user were typing fast
          //but we are interested only in responses that correspond to the current view value
          var onCurrentRequest = (inputValue === modelCtrl.$viewValue);
          if (onCurrentRequest && hasFocus) {
            if (matches.length > 0) {

              scope.activeIdx = focusFirst ? 0 : -1;
              scope.matches.length = 0;

              //transform labels
              for(var i=0; i<matches.length; i++) {
                locals[parserResult.itemName] = matches[i];
                scope.matches.push({
                  id: getMatchId(i),
                  label: parserResult.viewMapper(scope, locals),
                  model: matches[i]
                });
              }

              scope.query = inputValue;
              //position pop-up with matches - we need to re-calculate its position each time we are opening a window
              //with matches as a pop-up might be absolute-positioned and position of an input might have changed on a page
              //due to other elements being rendered
              scope.position = appendToBody ? $position.offset(element) : $position.position(element);
              scope.position.top = scope.position.top + element.prop('offsetHeight');

              element.attr('aria-expanded', true);
            } else {
              resetMatches();
            }
          }
          if (onCurrentRequest) {
            isLoadingSetter(originalScope, false);
          }
        }, function(){
          resetMatches();
          isLoadingSetter(originalScope, false);
        });
      };

      resetMatches();

      //we need to propagate user's query so we can higlight matches
      scope.query = undefined;

      //Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later 
      var timeoutPromise;

      var scheduleSearchWithTimeout = function(inputValue) {
        timeoutPromise = $timeout(function () {
          getMatchesAsync(inputValue);
        }, waitTime);
      };

      var cancelPreviousTimeout = function() {
        if (timeoutPromise) {
          $timeout.cancel(timeoutPromise);
        }
      };

      //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.unshift(function (inputValue) {

        hasFocus = true;

        if (inputValue && inputValue.length >= minSearch) {
          if (waitTime > 0) {
            cancelPreviousTimeout();
            scheduleSearchWithTimeout(inputValue);
          } else {
            getMatchesAsync(inputValue);
          }
        } else {
          isLoadingSetter(originalScope, false);
          cancelPreviousTimeout();
          resetMatches();
        }

        if (isEditable) {
          return inputValue;
        } else {
          if (!inputValue) {
            // Reset in case user had typed something previously.
            modelCtrl.$setValidity('editable', true);
            return inputValue;
          } else {
            modelCtrl.$setValidity('editable', false);
            return undefined;
          }
        }
      });

      modelCtrl.$formatters.push(function (modelValue) {

        var candidateViewValue, emptyViewValue;
        var locals = {};

        if (inputFormatter) {

          locals.$model = modelValue;
          return inputFormatter(originalScope, locals);

        } else {

          //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);
          locals[parserResult.itemName] = undefined;
          emptyViewValue = parserResult.viewMapper(originalScope, locals);

          return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue;
        }
      });

      scope.select = function (activeIdx) {
        //called from within the $digest() cycle
        var locals = {};
        var model, item;

        locals[parserResult.itemName] = item = scope.matches[activeIdx].model;
        model = parserResult.modelMapper(originalScope, locals);
        $setModelValue(originalScope, model);
        modelCtrl.$setValidity('editable', true);

        onSelectCallback(originalScope, {
          $item: item,
          $model: model,
          $label: parserResult.viewMapper(originalScope, locals)
        });

        resetMatches();

        //return focus to the input element if a match was selected via a mouse click event
        // use timeout to avoid $rootScope:inprog error
        $timeout(function() { element[0].focus(); }, 0, false);
      };

      //bind keyboard events: arrows up(38) / down(40), enter(13) and tab(9), esc(27)
      element.bind('keydown', function (evt) {

        //typeahead is open and an "interesting" key was pressed
        if (scope.matches.length === 0 || HOT_KEYS.indexOf(evt.which) === -1) {
          return;
        }

        // if there's nothing selected (i.e. focusFirst) and enter is hit, don't do anything
        if (scope.activeIdx == -1 && (evt.which === 13 || evt.which === 9)) {
          return;
        }

        evt.preventDefault();

        if (evt.which === 40) {
          scope.activeIdx = (scope.activeIdx + 1) % scope.matches.length;
          scope.$digest();

        } else if (evt.which === 38) {
          scope.activeIdx = (scope.activeIdx > 0 ? scope.activeIdx : scope.matches.length) - 1;
          scope.$digest();

        } else if (evt.which === 13 || evt.which === 9) {
          scope.$apply(function () {
            scope.select(scope.activeIdx);
          });

        } else if (evt.which === 27) {
          evt.stopPropagation();

          resetMatches();
          scope.$digest();
        }
      });

      element.bind('blur', function (evt) {
        hasFocus = false;
      });

      // 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);
        if (appendToBody) {
          $popup.remove();
        }
      });

      var $popup = $compile(popUpEl)(scope);
      if (appendToBody) {
        $document.find('body').append($popup);
      } else {
        element.after($popup);
      }
    }
  };

}])

  .directive('typeaheadPopup', function () {
    return {
      restrict:'EA',
      scope:{
        matches:'=',
        query:'=',
        active:'=',
        position:'=',
        select:'&'
      },
      replace:true,
      templateUrl:'template/typeahead/typeahead-popup.html',
      link:function (scope, element, attrs) {

        scope.templateUrl = attrs.templateUrl;

        scope.isOpen = function () {
          return scope.matches.length > 0;
        };

        scope.isActive = function (matchIdx) {
          return scope.active == matchIdx;
        };

        scope.selectActive = function (matchIdx) {
          scope.active = matchIdx;
        };

        scope.selectMatch = function (activeIdx) {
          scope.select({activeIdx:activeIdx});
        };
      }
    };
  })

  .directive('typeaheadMatch', ['$http', '$templateCache', '$compile', '$parse', function ($http, $templateCache, $compile, $parse) {
    return {
      restrict:'EA',
      scope:{
        index:'=',
        match:'=',
        query:'='
      },
      link:function (scope, element, attrs) {
        var tplUrl = $parse(attrs.templateUrl)(scope.$parent) || 'template/typeahead/typeahead-match.html';
        $http.get(tplUrl, {cache: $templateCache}).success(function(tplContent){
           element.replaceWith($compile(tplContent.trim())(scope));
        });
      }
    };
  }])

  .filter('typeaheadHighlight', function() {

    function escapeRegexp(queryToEscape) {
      return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
    }

    return function(matchItem, query) {
      return query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchItem;
    };
  });

angular.module("template/accordion/accordion-group.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/accordion/accordion-group.html",
    "<div class=\"panel panel-default\">\n" +
    "  <div class=\"panel-heading\">\n" +
    "    <h4 class=\"panel-title\">\n" +
    "      <a href class=\"accordion-toggle\" ng-click=\"toggleOpen()\" accordion-transclude=\"heading\"><span ng-class=\"{'text-muted': isDisabled}\">{{heading}}</span></a>\n" +
    "    </h4>\n" +
    "  </div>\n" +
    "  <div class=\"panel-collapse\" collapse=\"!isOpen\">\n" +
    "	  <div class=\"panel-body\" ng-transclude></div>\n" +
    "  </div>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/accordion/accordion.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/accordion/accordion.html",
    "<div class=\"panel-group\" ng-transclude></div>");
}]);

angular.module("template/alert/alert.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/alert/alert.html",
    "<div class=\"alert\" ng-class=\"['alert-' + (type || 'warning'), closeable ? 'alert-dismissable' : null]\" role=\"alert\">\n" +
    "    <button ng-show=\"closeable\" type=\"button\" class=\"close\" ng-click=\"close()\">\n" +
    "        <span aria-hidden=\"true\">&times;</span>\n" +
    "        <span class=\"sr-only\">Close</span>\n" +
    "    </button>\n" +
    "    <div ng-transclude></div>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/carousel/carousel.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/carousel/carousel.html",
    "<div ng-mouseenter=\"pause()\" ng-mouseleave=\"play()\" class=\"carousel\" ng-swipe-right=\"prev()\" ng-swipe-left=\"next()\">\n" +
    "    <ol class=\"carousel-indicators\" ng-show=\"slides.length > 1\">\n" +
    "        <li ng-repeat=\"slide in slides track by $index\" ng-class=\"{active: isActive(slide)}\" ng-click=\"select(slide)\"></li>\n" +
    "    </ol>\n" +
    "    <div class=\"carousel-inner\" ng-transclude></div>\n" +
    "    <a class=\"left carousel-control\" ng-click=\"prev()\" ng-show=\"slides.length > 1\"><span class=\"glyphicon glyphicon-chevron-left\"></span></a>\n" +
    "    <a class=\"right carousel-control\" ng-click=\"next()\" ng-show=\"slides.length > 1\"><span class=\"glyphicon glyphicon-chevron-right\"></span></a>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/carousel/slide.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/carousel/slide.html",
    "<div ng-class=\"{\n" +
    "    'active': leaving || (active && !entering),\n" +
    "    'prev': (next || active) && direction=='prev',\n" +
    "    'next': (next || active) && direction=='next',\n" +
    "    'right': direction=='prev',\n" +
    "    'left': direction=='next'\n" +
    "  }\" class=\"item text-center\" ng-transclude></div>\n" +
    "");
}]);

angular.module("template/datepicker/datepicker.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/datepicker/datepicker.html",
    "<div ng-switch=\"datepickerMode\" role=\"application\" ng-keydown=\"keydown($event)\">\n" +
    "  <daypicker ng-switch-when=\"day\" tabindex=\"0\"></daypicker>\n" +
    "  <monthpicker ng-switch-when=\"month\" tabindex=\"0\"></monthpicker>\n" +
    "  <yearpicker ng-switch-when=\"year\" tabindex=\"0\"></yearpicker>\n" +
    "</div>");
}]);

angular.module("template/datepicker/day.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/datepicker/day.html",
    "<table role=\"grid\" aria-labelledby=\"{{uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
    "  <thead>\n" +
    "    <tr>\n" +
    "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
    "      <th colspan=\"{{5 + showWeeks}}\"><button id=\"{{uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm\" ng-click=\"toggleMode()\" tabindex=\"-1\" style=\"width:100%;\"><strong>{{title}}</strong></button></th>\n" +
    "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
    "    </tr>\n" +
    "    <tr>\n" +
    "      <th ng-show=\"showWeeks\" class=\"text-center\"></th>\n" +
    "      <th ng-repeat=\"label in labels track by $index\" class=\"text-center\"><small aria-label=\"{{label.full}}\">{{label.abbr}}</small></th>\n" +
    "    </tr>\n" +
    "  </thead>\n" +
    "  <tbody>\n" +
    "    <tr ng-repeat=\"row in rows track by $index\">\n" +
    "      <td ng-show=\"showWeeks\" class=\"text-center h6\"><em>{{ weekNumbers[$index] }}</em></td>\n" +
    "      <td ng-repeat=\"dt in row track by dt.date\" class=\"text-center\" role=\"gridcell\" id=\"{{dt.uid}}\" aria-disabled=\"{{!!dt.disabled}}\">\n" +
    "        <button type=\"button\" style=\"width:100%;\" class=\"btn btn-default btn-sm\" ng-class=\"{'btn-info': dt.selected, active: isActive(dt)}\" ng-click=\"select(dt.date)\" ng-disabled=\"dt.disabled\" tabindex=\"-1\"><span ng-class=\"{'text-muted': dt.secondary, 'text-info': dt.current}\">{{dt.label}}</span></button>\n" +
    "      </td>\n" +
    "    </tr>\n" +
    "  </tbody>\n" +
    "</table>\n" +
    "");
}]);

angular.module("template/datepicker/month.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/datepicker/month.html",
    "<table role=\"grid\" aria-labelledby=\"{{uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
    "  <thead>\n" +
    "    <tr>\n" +
    "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
    "      <th><button id=\"{{uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm\" ng-click=\"toggleMode()\" tabindex=\"-1\" style=\"width:100%;\"><strong>{{title}}</strong></button></th>\n" +
    "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
    "    </tr>\n" +
    "  </thead>\n" +
    "  <tbody>\n" +
    "    <tr ng-repeat=\"row in rows track by $index\">\n" +
    "      <td ng-repeat=\"dt in row track by dt.date\" class=\"text-center\" role=\"gridcell\" id=\"{{dt.uid}}\" aria-disabled=\"{{!!dt.disabled}}\">\n" +
    "        <button type=\"button\" style=\"width:100%;\" class=\"btn btn-default\" ng-class=\"{'btn-info': dt.selected, active: isActive(dt)}\" ng-click=\"select(dt.date)\" ng-disabled=\"dt.disabled\" tabindex=\"-1\"><span ng-class=\"{'text-info': dt.current}\">{{dt.label}}</span></button>\n" +
    "      </td>\n" +
    "    </tr>\n" +
    "  </tbody>\n" +
    "</table>\n" +
    "");
}]);

angular.module("template/datepicker/popup.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/datepicker/popup.html",
    "<ul class=\"dropdown-menu\" ng-style=\"{display: (isOpen && 'block') || 'none', top: position.top+'px', left: position.left+'px'}\" ng-keydown=\"keydown($event)\">\n" +
    "	<li ng-transclude></li>\n" +
    "	<li ng-if=\"showButtonBar\" style=\"padding:10px 9px 2px\">\n" +
    "		<span class=\"btn-group pull-left\">\n" +
    "			<button type=\"button\" class=\"btn btn-sm btn-info\" ng-click=\"select('today')\">{{ getText('current') }}</button>\n" +
    "			<button type=\"button\" class=\"btn btn-sm btn-danger\" ng-click=\"select(null)\">{{ getText('clear') }}</button>\n" +
    "		</span>\n" +
    "		<button type=\"button\" class=\"btn btn-sm btn-success pull-right\" ng-click=\"close()\">{{ getText('close') }}</button>\n" +
    "	</li>\n" +
    "</ul>\n" +
    "");
}]);

angular.module("template/datepicker/year.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/datepicker/year.html",
    "<table role=\"grid\" aria-labelledby=\"{{uniqueId}}-title\" aria-activedescendant=\"{{activeDateId}}\">\n" +
    "  <thead>\n" +
    "    <tr>\n" +
    "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-left\" ng-click=\"move(-1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-left\"></i></button></th>\n" +
    "      <th colspan=\"3\"><button id=\"{{uniqueId}}-title\" role=\"heading\" aria-live=\"assertive\" aria-atomic=\"true\" type=\"button\" class=\"btn btn-default btn-sm\" ng-click=\"toggleMode()\" tabindex=\"-1\" style=\"width:100%;\"><strong>{{title}}</strong></button></th>\n" +
    "      <th><button type=\"button\" class=\"btn btn-default btn-sm pull-right\" ng-click=\"move(1)\" tabindex=\"-1\"><i class=\"glyphicon glyphicon-chevron-right\"></i></button></th>\n" +
    "    </tr>\n" +
    "  </thead>\n" +
    "  <tbody>\n" +
    "    <tr ng-repeat=\"row in rows track by $index\">\n" +
    "      <td ng-repeat=\"dt in row track by dt.date\" class=\"text-center\" role=\"gridcell\" id=\"{{dt.uid}}\" aria-disabled=\"{{!!dt.disabled}}\">\n" +
    "        <button type=\"button\" style=\"width:100%;\" class=\"btn btn-default\" ng-class=\"{'btn-info': dt.selected, active: isActive(dt)}\" ng-click=\"select(dt.date)\" ng-disabled=\"dt.disabled\" tabindex=\"-1\"><span ng-class=\"{'text-info': dt.current}\">{{dt.label}}</span></button>\n" +
    "      </td>\n" +
    "    </tr>\n" +
    "  </tbody>\n" +
    "</table>\n" +
    "");
}]);

angular.module("template/modal/backdrop.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/modal/backdrop.html",
    "<div class=\"modal-backdrop fade {{ backdropClass }}\"\n" +
    "     ng-class=\"{in: animate}\"\n" +
    "     ng-style=\"{'z-index': 9999999 + (index && 1 || 0) + index*10}\"\n" +
    "></div>\n" +
    "");
}]);

angular.module("template/modal/window.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/modal/window.html",
    "<div tabindex=\"-1\" role=\"dialog\" class=\"modal fade\" ng-class=\"{in: animate}\" ng-style=\"{'z-index': 99999999 + index*10, display: 'block'}\" ng-click=\"close($event)\">\n" +
    "    <div class=\"modal-dialog\" ng-class=\"{'modal-sm': size == 'sm', 'modal-lg': size == 'lg'}\"><div class=\"modal-content\" modal-transclude></div></div>\n" +
    "</div>");
}]);

angular.module("template/pagination/pager.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/pagination/pager.html",
    "<ul class=\"pager\">\n" +
    "  <li ng-class=\"{disabled: noPrevious(), previous: align}\"><a href ng-click=\"selectPage(page - 1)\">{{getText('previous')}}</a></li>\n" +
    "  <li ng-class=\"{disabled: noNext(), next: align}\"><a href ng-click=\"selectPage(page + 1)\">{{getText('next')}}</a></li>\n" +
    "</ul>");
}]);

angular.module("template/pagination/pagination.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/pagination/pagination.html",
    "<ul class=\"pagination\">\n" +
    "  <li ng-if=\"boundaryLinks\" ng-class=\"{disabled: noPrevious()}\"><a href ng-click=\"selectPage(1)\">{{getText('first')}}</a></li>\n" +
    "  <li ng-if=\"directionLinks\" ng-class=\"{disabled: noPrevious()}\"><a href ng-click=\"selectPage(page - 1)\">{{getText('previous')}}</a></li>\n" +
    "  <li ng-repeat=\"page in pages track by $index\" ng-class=\"{active: page.active}\"><a href ng-click=\"selectPage(page.number)\">{{page.text}}</a></li>\n" +
    "  <li ng-if=\"directionLinks\" ng-class=\"{disabled: noNext()}\"><a href ng-click=\"selectPage(page + 1)\">{{getText('next')}}</a></li>\n" +
    "  <li ng-if=\"boundaryLinks\" ng-class=\"{disabled: noNext()}\"><a href ng-click=\"selectPage(totalPages)\">{{getText('last')}}</a></li>\n" +
    "</ul>");
}]);

angular.module("template/tooltip/tooltip-html-unsafe-popup.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/tooltip/tooltip-html-unsafe-popup.html",
    "<div class=\"tooltip {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
    "  <div class=\"tooltip-arrow\"></div>\n" +
    "  <div class=\"tooltip-inner\" bind-html-unsafe=\"content\"></div>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/tooltip/tooltip-popup.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/tooltip/tooltip-popup.html",
    "<div class=\"tooltip {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
    "  <div class=\"tooltip-arrow\"></div>\n" +
    "  <div class=\"tooltip-inner\" ng-bind=\"content\"></div>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/popover/popover.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/popover/popover.html",
    "<div class=\"popover {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
    "  <div class=\"arrow\"></div>\n" +
    "\n" +
    "  <div class=\"popover-inner\">\n" +
    "      <h3 class=\"popover-title\" ng-bind=\"title\" ng-show=\"title\"></h3>\n" +
    "      <div class=\"popover-content\" ng-bind=\"content\"></div>\n" +
    "  </div>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/progressbar/bar.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/progressbar/bar.html",
    "<div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" role=\"progressbar\" aria-valuenow=\"{{value}}\" aria-valuemin=\"0\" aria-valuemax=\"{{max}}\" ng-style=\"{width: percent + '%'}\" aria-valuetext=\"{{percent | number:0}}%\" ng-transclude></div>");
}]);

angular.module("template/progressbar/progress.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/progressbar/progress.html",
    "<div class=\"progress\" ng-transclude></div>");
}]);

angular.module("template/progressbar/progressbar.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/progressbar/progressbar.html",
    "<div class=\"progress\">\n" +
    "  <div class=\"progress-bar\" ng-class=\"type && 'progress-bar-' + type\" role=\"progressbar\" aria-valuenow=\"{{value}}\" aria-valuemin=\"0\" aria-valuemax=\"{{max}}\" ng-style=\"{width: percent + '%'}\" aria-valuetext=\"{{percent | number:0}}%\" ng-transclude></div>\n" +
    "</div>");
}]);

angular.module("template/rating/rating.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/rating/rating.html",
    "<span ng-mouseleave=\"reset()\" ng-keydown=\"onKeydown($event)\" tabindex=\"0\" role=\"slider\" aria-valuemin=\"0\" aria-valuemax=\"{{range.length}}\" aria-valuenow=\"{{value}}\">\n" +
    "    <i ng-repeat=\"r in range track by $index\" ng-mouseenter=\"enter($index + 1)\" ng-click=\"rate($index + 1)\" class=\"glyphicon\" ng-class=\"$index < value && (r.stateOn || 'glyphicon-star') || (r.stateOff || 'glyphicon-star-empty')\">\n" +
    "        <span class=\"sr-only\">({{ $index < value ? '*' : ' ' }})</span>\n" +
    "    </i>\n" +
    "</span>");
}]);

angular.module("template/tabs/tab.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/tabs/tab.html",
    "<li ng-class=\"{active: active, disabled: disabled}\">\n" +
    "  <a href ng-click=\"select()\" tab-heading-transclude>{{heading}}</a>\n" +
    "</li>\n" +
    "");
}]);

angular.module("template/tabs/tabset.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/tabs/tabset.html",
    "<div>\n" +
    "  <ul class=\"nav nav-{{type || 'tabs'}}\" ng-class=\"{'nav-stacked': vertical, 'nav-justified': justified}\" ng-transclude></ul>\n" +
    "  <div class=\"tab-content\">\n" +
    "    <div class=\"tab-pane\" \n" +
    "         ng-repeat=\"tab in tabs\" \n" +
    "         ng-class=\"{active: tab.active}\"\n" +
    "         tab-content-transclude=\"tab\">\n" +
    "    </div>\n" +
    "  </div>\n" +
    "</div>\n" +
    "");
}]);

angular.module("template/timepicker/timepicker.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/timepicker/timepicker.html",
    "<table>\n" +
    "	<tbody>\n" +
    "		<tr class=\"text-center\">\n" +
    "			<td><a ng-click=\"incrementHours()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
    "			<td>&nbsp;</td>\n" +
    "			<td><a ng-click=\"incrementMinutes()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-up\"></span></a></td>\n" +
    "			<td ng-show=\"showMeridian\"></td>\n" +
    "		</tr>\n" +
    "		<tr>\n" +
    "			<td style=\"width:50px;\" class=\"form-group\" ng-class=\"{'has-error': invalidHours}\">\n" +
    "				<input type=\"text\" ng-model=\"hours\" ng-change=\"updateHours()\" class=\"form-control text-center\" ng-mousewheel=\"incrementHours()\" ng-readonly=\"readonlyInput\" maxlength=\"2\">\n" +
    "			</td>\n" +
    "			<td>:</td>\n" +
    "			<td style=\"width:50px;\" class=\"form-group\" ng-class=\"{'has-error': invalidMinutes}\">\n" +
    "				<input type=\"text\" ng-model=\"minutes\" ng-change=\"updateMinutes()\" class=\"form-control text-center\" ng-readonly=\"readonlyInput\" maxlength=\"2\">\n" +
    "			</td>\n" +
    "			<td ng-show=\"showMeridian\"><button type=\"button\" class=\"btn btn-default text-center\" ng-click=\"toggleMeridian()\">{{meridian}}</button></td>\n" +
    "		</tr>\n" +
    "		<tr class=\"text-center\">\n" +
    "			<td><a ng-click=\"decrementHours()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
    "			<td>&nbsp;</td>\n" +
    "			<td><a ng-click=\"decrementMinutes()\" class=\"btn btn-link\"><span class=\"glyphicon glyphicon-chevron-down\"></span></a></td>\n" +
    "			<td ng-show=\"showMeridian\"></td>\n" +
    "		</tr>\n" +
    "	</tbody>\n" +
    "</table>\n" +
    "");
}]);

angular.module("template/typeahead/typeahead-match.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/typeahead/typeahead-match.html",
    "<a tabindex=\"-1\" bind-html-unsafe=\"match.label | typeaheadHighlight:query\"></a>");
}]);

angular.module("template/typeahead/typeahead-popup.html", []).run(["$templateCache", function($templateCache) {
  $templateCache.put("template/typeahead/typeahead-popup.html",
    "<ul class=\"dropdown-menu\" ng-show=\"isOpen()\" ng-style=\"{top: position.top+'px', left: position.left+'px'}\" style=\"display: block;\" role=\"listbox\" aria-hidden=\"{{!isOpen()}}\">\n" +
    "    <li ng-repeat=\"match in matches track by $index\" ng-class=\"{active: isActive($index) }\" ng-mouseenter=\"selectActive($index)\" ng-click=\"selectMatch($index)\" role=\"option\" id=\"{{match.id}}\">\n" +
    "        <div typeahead-match index=\"$index\" match=\"match\" query=\"query\" template-url=\"templateUrl\"></div>\n" +
    "    </li>\n" +
    "</ul>\n" +
    "");
}]);

(function() {
    'use strict';
    
    var module = angular.module('oneKeyApp');
    
    var dynamicLinkCtrl = function(featureToggle, $timeout){
        var vm = this;
        vm.getFeatures = getFeatures;
        vm.enableFeature = false;
        function getFeatures(){
            featureToggle.getAll()
            .then(function(response) {
                $timeout(function(){
                    vm.enableFeature = response.places;
                }, 0);
            });
        }
        getFeatures();
    };
    
    module.controller('dynamicLinkCtrl', dynamicLinkCtrl);
    dynamicLinkCtrl.$inject = ['featureToggle', '$timeout'];
    
    function metDynamicLink(host) {
        var directive = {
            restrict: 'EA',
            replace: true,
            transclude: true,
            scope: {
                routesTo: '@',
                enableFeature: '=',
                linkText: '@',
                metClass: '=',
                hasNewBadge: '='
            },
            link: function(scope, el, attr, $ctrl, transclude){
                scope.metClass = attr.metClass;
                scope.linkText = attr.linkText;
                scope.routesTo = attr.routesTo;

                // Polyfill for IE.
                if (!String.prototype.startsWith) {
                    String.prototype.startsWith = function (searchString, position) {
                        position = position || 0;
                        return this.indexOf(searchString, position) === position;
                    };
                }
                
                var cls = attr.metClass;
                el.addClass(cls);
                 scope.$watch('vm.enableFeature', function(value){
                    if (value === true) {
                        transclude(function () {
                            var elementToInsert = '<li><div><a href="' + scope.routesTo + '">' + scope.linkText + '</a></div></li>';
                            if (scope.vm.hasNewBadge) {
                                if (host.languageSegment().length > 5) {
                                    elementToInsert = '<li><div class="nav-new-badge-container"><a href="' +
                                        scope.routesTo +
                                        '">' +
                                        scope.linkText +
                                        '</a><div class="nav-new-badge">New</div></div></li>';
                                } else {
                                    elementToInsert = '<li><div class="nav-new-badge-container"><a href="' +
                                        scope.routesTo +
                                        '">' +
                                        scope.linkText +
                                        '</a><div class="nav-new-badge"></div></div></li>';
                                }
                            }
                            
                            el.after(elementToInsert);
                        });
                    }
                });
                
            },
            controller: 'dynamicLinkCtrl as vm',
            bindToController: true
        };
        return directive;
    }
    module.directive('metDynamicLink', metDynamicLink);
    metDynamicLink.$inject = ['host'];
    
}());
/*!
 * angular-translate - v2.7.2 - 2015-06-01
 * http://github.com/angular-translate/angular-translate
 * Copyright (c) 2015 ; Licensed MIT
 */
!function(a,b){"function"==typeof define&&define.amd?define([],function(){return b()}):"object"==typeof exports?module.exports=b():b()}(this,function(){function a(a){"use strict";var b=a.storageKey(),c=a.storage(),d=function(){var d=a.preferredLanguage();angular.isString(d)?a.use(d):c.put(b,a.use())};d.displayName="fallbackFromIncorrectStorageValue",c?c.get(b)?a.use(c.get(b))["catch"](d):d():angular.isString(a.preferredLanguage())&&a.use(a.preferredLanguage())}function b(){"use strict";var a,b,c=null,d=!1,e=!1;b={sanitize:function(a,b){return"text"===b&&(a=g(a)),a},escape:function(a,b){return"text"===b&&(a=f(a)),a},sanitizeParameters:function(a,b){return"params"===b&&(a=h(a,g)),a},escapeParameters:function(a,b){return"params"===b&&(a=h(a,f)),a}},b.escaped=b.escapeParameters,this.addStrategy=function(a,c){return b[a]=c,this},this.removeStrategy=function(a){return delete b[a],this},this.useStrategy=function(a){return d=!0,c=a,this},this.$get=["$injector","$log",function(f,g){var h=function(a,c,d){return angular.forEach(d,function(d){if(angular.isFunction(d))a=d(a,c);else{if(!angular.isFunction(b[d]))throw new Error("pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: '"+d+"'");a=b[d](a,c)}}),a},i=function(){d||e||(g.warn("pascalprecht.translate.$translateSanitization: No sanitization strategy has been configured. This can have serious security implications. See http://angular-translate.github.io/docs/#/guide/19_security for details."),e=!0)};return f.has("$sanitize")&&(a=f.get("$sanitize")),{useStrategy:function(a){return function(b){a.useStrategy(b)}}(this),sanitize:function(a,b,d){if(c||i(),arguments.length<3&&(d=c),!d)return a;var e=angular.isArray(d)?d:[d];return h(a,b,e)}}}];var f=function(a){var b=angular.element("<div></div>");return b.text(a),b.html()},g=function(b){if(!a)throw new Error("pascalprecht.translate.$translateSanitization: Error cannot find $sanitize service. Either include the ngSanitize module (https://docs.angularjs.org/api/ngSanitize) or use a sanitization strategy which does not depend on $sanitize, such as 'escape'.");return a(b)},h=function(a,b){if(angular.isObject(a)){var c=angular.isArray(a)?[]:{};return angular.forEach(a,function(a,d){c[d]=h(a,b)}),c}return angular.isNumber(a)?a:b(a)}}function c(a,b,c,d){"use strict";var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t={},u=[],v=a,w=[],x="translate-cloak",y=!1,z=!1,A=".",B=0,C=!0,D="default",E={"default":function(a){return(a||"").split("-").join("_")},java:function(a){var b=(a||"").split("-").join("_"),c=b.split("_");return c.length>1?c[0].toLowerCase()+"_"+c[1].toUpperCase():b},bcp47:function(a){var b=(a||"").split("_").join("-"),c=b.split("-");return c.length>1?c[0].toLowerCase()+"-"+c[1].toUpperCase():b}},F="2.7.2",G=function(){if(angular.isFunction(d.getLocale))return d.getLocale();var a,c,e=b.$get().navigator,f=["language","browserLanguage","systemLanguage","userLanguage"];if(angular.isArray(e.languages))for(a=0;a<e.languages.length;a++)if(c=e.languages[a],c&&c.length)return c;for(a=0;a<f.length;a++)if(c=e[f[a]],c&&c.length)return c;return null};G.displayName="angular-translate/service: getFirstBrowserLanguage";var H=function(){var a=G()||"";return E[D]&&(a=E[D](a)),a};H.displayName="angular-translate/service: getLocale";var I=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},J=function(){return this.toString().replace(/^\s+|\s+$/g,"")},K=function(a){for(var b=[],c=angular.lowercase(a),d=0,e=u.length;e>d;d++)b.push(angular.lowercase(u[d]));if(I(b,c)>-1)return a;if(f){var g;for(var h in f){var i=!1,j=Object.prototype.hasOwnProperty.call(f,h)&&angular.lowercase(h)===angular.lowercase(a);if("*"===h.slice(-1)&&(i=h.slice(0,-1)===a.slice(0,h.length-1)),(j||i)&&(g=f[h],I(b,angular.lowercase(g))>-1))return g}}if(a){var k=a.split("_");if(k.length>1&&I(b,angular.lowercase(k[0]))>-1)return k[0]}return a},L=function(a,b){if(!a&&!b)return t;if(a&&!b){if(angular.isString(a))return t[a]}else angular.isObject(t[a])||(t[a]={}),angular.extend(t[a],M(b));return this};this.translations=L,this.cloakClassName=function(a){return a?(x=a,this):x};var M=function(a,b,c,d){var e,f,g,h;b||(b=[]),c||(c={});for(e in a)Object.prototype.hasOwnProperty.call(a,e)&&(h=a[e],angular.isObject(h)?M(h,b.concat(e),c,e):(f=b.length?""+b.join(A)+A+e:e,b.length&&e===d&&(g=""+b.join(A),c[g]="@:"+f),c[f]=h));return c};M.displayName="flatObject",this.addInterpolation=function(a){return w.push(a),this},this.useMessageFormatInterpolation=function(){return this.useInterpolation("$translateMessageFormatInterpolation")},this.useInterpolation=function(a){return n=a,this},this.useSanitizeValueStrategy=function(a){return c.useStrategy(a),this},this.preferredLanguage=function(a){return N(a),this};var N=function(a){return a&&(e=a),e};this.translationNotFoundIndicator=function(a){return this.translationNotFoundIndicatorLeft(a),this.translationNotFoundIndicatorRight(a),this},this.translationNotFoundIndicatorLeft=function(a){return a?(q=a,this):q},this.translationNotFoundIndicatorRight=function(a){return a?(r=a,this):r},this.fallbackLanguage=function(a){return O(a),this};var O=function(a){return a?(angular.isString(a)?(h=!0,g=[a]):angular.isArray(a)&&(h=!1,g=a),angular.isString(e)&&I(g,e)<0&&g.push(e),this):h?g[0]:g};this.use=function(a){if(a){if(!t[a]&&!o)throw new Error("$translateProvider couldn't find translationTable for langKey: '"+a+"'");return i=a,this}return i};var P=function(a){return a?(v=a,this):l?l+v:v};this.storageKey=P,this.useUrlLoader=function(a,b){return this.useLoader("$translateUrlLoader",angular.extend({url:a},b))},this.useStaticFilesLoader=function(a){return this.useLoader("$translateStaticFilesLoader",a)},this.useLoader=function(a,b){return o=a,p=b||{},this},this.useLocalStorage=function(){return this.useStorage("$translateLocalStorage")},this.useCookieStorage=function(){return this.useStorage("$translateCookieStorage")},this.useStorage=function(a){return k=a,this},this.storagePrefix=function(a){return a?(l=a,this):a},this.useMissingTranslationHandlerLog=function(){return this.useMissingTranslationHandler("$translateMissingTranslationHandlerLog")},this.useMissingTranslationHandler=function(a){return m=a,this},this.usePostCompiling=function(a){return y=!!a,this},this.forceAsyncReload=function(a){return z=!!a,this},this.uniformLanguageTag=function(a){return a?angular.isString(a)&&(a={standard:a}):a={},D=a.standard,this},this.determinePreferredLanguage=function(a){var b=a&&angular.isFunction(a)?a():H();return e=u.length?K(b):b,this},this.registerAvailableLanguageKeys=function(a,b){return a?(u=a,b&&(f=b),this):u},this.useLoaderCache=function(a){return a===!1?s=void 0:a===!0?s=!0:"undefined"==typeof a?s="$translationCache":a&&(s=a),this},this.directivePriority=function(a){return void 0===a?B:(B=a,this)},this.statefulFilter=function(a){return void 0===a?C:(C=a,this)},this.$get=["$log","$injector","$rootScope","$q",function(a,b,c,d){var f,l,u,A=b.get(n||"$translateDefaultInterpolation"),D=!1,E={},G={},H=function(a,b,c,h){if(angular.isArray(a)){var j=function(a){for(var e={},f=[],g=function(a){var f=d.defer(),g=function(b){e[a]=b,f.resolve([a,b])};return H(a,b,c,h).then(g,g),f.promise},i=0,j=a.length;j>i;i++)f.push(g(a[i]));return d.all(f).then(function(){return e})};return j(a)}var m=d.defer();a&&(a=J.apply(a));var n=function(){var a=e?G[e]:G[i];if(l=0,k&&!a){var b=f.get(v);if(a=G[b],g&&g.length){var c=I(g,b);l=0===c?1:0,I(g,e)<0&&g.push(e)}}return a}();if(n){var o=function(){ab(a,b,c,h).then(m.resolve,m.reject)};o.displayName="promiseResolved",n["finally"](o,m.reject)}else ab(a,b,c,h).then(m.resolve,m.reject);return m.promise},Q=function(a){return q&&(a=[q,a].join(" ")),r&&(a=[a,r].join(" ")),a},R=function(a){i=a,c.$emit("$translateChangeSuccess",{language:a}),k&&f.put(H.storageKey(),i),A.setLocale(i);var b=function(a,b){E[b].setLocale(i)};b.displayName="eachInterpolatorLocaleSetter",angular.forEach(E,b),c.$emit("$translateChangeEnd",{language:a})},S=function(a){if(!a)throw"No language key specified for loading.";var e=d.defer();c.$emit("$translateLoadingStart",{language:a}),D=!0;var f=s;"string"==typeof f&&(f=b.get(f));var g=angular.extend({},p,{key:a,$http:angular.extend({},{cache:f},p.$http)}),h=function(b){var d={};c.$emit("$translateLoadingSuccess",{language:a}),angular.isArray(b)?angular.forEach(b,function(a){angular.extend(d,M(a))}):angular.extend(d,M(b)),D=!1,e.resolve({key:a,table:d}),c.$emit("$translateLoadingEnd",{language:a})};h.displayName="onLoaderSuccess";var i=function(a){c.$emit("$translateLoadingError",{language:a}),e.reject(a),c.$emit("$translateLoadingEnd",{language:a})};return i.displayName="onLoaderError",b.get(o)(g).then(h,i),e.promise};if(k&&(f=b.get(k),!f.get||!f.put))throw new Error("Couldn't use storage '"+k+"', missing get() or put() method!");if(w.length){var T=function(a){var c=b.get(a);c.setLocale(e||i),E[c.getInterpolationIdentifier()]=c};T.displayName="interpolationFactoryAdder",angular.forEach(w,T)}var U=function(a){var b=d.defer();if(Object.prototype.hasOwnProperty.call(t,a))b.resolve(t[a]);else if(G[a]){var c=function(a){L(a.key,a.table),b.resolve(a.table)};c.displayName="translationTableResolver",G[a].then(c,b.reject)}else b.reject();return b.promise},V=function(a,b,c,e){var f=d.defer(),g=function(d){if(Object.prototype.hasOwnProperty.call(d,b)){e.setLocale(a);var g=d[b];"@:"===g.substr(0,2)?V(a,g.substr(2),c,e).then(f.resolve,f.reject):f.resolve(e.interpolate(d[b],c)),e.setLocale(i)}else f.reject()};return g.displayName="fallbackTranslationResolver",U(a).then(g,f.reject),f.promise},W=function(a,b,c,d){var e,f=t[a];if(f&&Object.prototype.hasOwnProperty.call(f,b)){if(d.setLocale(a),e=d.interpolate(f[b],c),"@:"===e.substr(0,2))return W(a,e.substr(2),c,d);d.setLocale(i)}return e},X=function(a,c){if(m){var d=b.get(m)(a,i,c);return void 0!==d?d:a}return a},Y=function(a,b,c,e,f){var h=d.defer();if(a<g.length){var i=g[a];V(i,b,c,e).then(h.resolve,function(){Y(a+1,b,c,e,f).then(h.resolve)})}else h.resolve(f?f:X(b,c));return h.promise},Z=function(a,b,c,d){var e;if(a<g.length){var f=g[a];e=W(f,b,c,d),e||(e=Z(a+1,b,c,d))}return e},$=function(a,b,c,d){return Y(u>0?u:l,a,b,c,d)},_=function(a,b,c){return Z(u>0?u:l,a,b,c)},ab=function(a,b,c,e){var f=d.defer(),h=i?t[i]:t,j=c?E[c]:A;if(h&&Object.prototype.hasOwnProperty.call(h,a)){var k=h[a];"@:"===k.substr(0,2)?H(k.substr(2),b,c,e).then(f.resolve,f.reject):f.resolve(j.interpolate(k,b))}else{var l;m&&!D&&(l=X(a,b)),i&&g&&g.length?$(a,b,j,e).then(function(a){f.resolve(a)},function(a){f.reject(Q(a))}):m&&!D&&l?f.resolve(e?e:l):e?f.resolve(e):f.reject(Q(a))}return f.promise},bb=function(a,b,c){var d,e=i?t[i]:t,f=A;if(E&&Object.prototype.hasOwnProperty.call(E,c)&&(f=E[c]),e&&Object.prototype.hasOwnProperty.call(e,a)){var h=e[a];d="@:"===h.substr(0,2)?bb(h.substr(2),b,c):f.interpolate(h,b)}else{var j;m&&!D&&(j=X(a,b)),i&&g&&g.length?(l=0,d=_(a,b,f)):d=m&&!D&&j?j:Q(a)}return d},cb=function(a){j===a&&(j=void 0),G[a]=void 0};if(H.preferredLanguage=function(a){return a&&N(a),e},H.cloakClassName=function(){return x},H.fallbackLanguage=function(a){if(void 0!==a&&null!==a){if(O(a),o&&g&&g.length)for(var b=0,c=g.length;c>b;b++)G[g[b]]||(G[g[b]]=S(g[b]));H.use(H.use())}return h?g[0]:g},H.useFallbackLanguage=function(a){if(void 0!==a&&null!==a)if(a){var b=I(g,a);b>-1&&(u=b)}else u=0},H.proposedLanguage=function(){return j},H.storage=function(){return f},H.use=function(a){if(!a)return i;var b=d.defer();c.$emit("$translateChangeStart",{language:a});var e=K(a);return e&&(a=e),!z&&t[a]||!o||G[a]?j===a&&G[a]?G[a].then(function(a){return b.resolve(a.key),a},function(a){return b.reject(a),d.reject(a)}):(b.resolve(a),R(a)):(j=a,G[a]=S(a).then(function(a){return L(a.key,a.table),b.resolve(a.key),R(a.key),a},function(a){return c.$emit("$translateChangeError",{language:a}),b.reject(a),c.$emit("$translateChangeEnd",{language:a}),d.reject(a)}),G[a]["finally"](function(){cb(a)})),b.promise},H.storageKey=function(){return P()},H.isPostCompilingEnabled=function(){return y},H.isForceAsyncReloadEnabled=function(){return z},H.refresh=function(a){function b(){f.resolve(),c.$emit("$translateRefreshEnd",{language:a})}function e(){f.reject(),c.$emit("$translateRefreshEnd",{language:a})}if(!o)throw new Error("Couldn't refresh translation table, no loader registered!");var f=d.defer();if(c.$emit("$translateRefreshStart",{language:a}),a)if(t[a]){var h=function(c){L(c.key,c.table),a===i&&R(i),b()};h.displayName="refreshPostProcessor",S(a).then(h,e)}else e();else{var j=[],k={};if(g&&g.length)for(var l=0,m=g.length;m>l;l++)j.push(S(g[l])),k[g[l]]=!0;i&&!k[i]&&j.push(S(i));var n=function(a){t={},angular.forEach(a,function(a){L(a.key,a.table)}),i&&R(i),b()};n.displayName="refreshPostProcessor",d.all(j).then(n,e)}return f.promise},H.instant=function(a,b,c){if(null===a||angular.isUndefined(a))return a;if(angular.isArray(a)){for(var d={},f=0,h=a.length;h>f;f++)d[a[f]]=H.instant(a[f],b,c);return d}if(angular.isString(a)&&a.length<1)return a;a&&(a=J.apply(a));var j,k=[];e&&k.push(e),i&&k.push(i),g&&g.length&&(k=k.concat(g));for(var l=0,n=k.length;n>l;l++){var o=k[l];if(t[o]&&("undefined"!=typeof t[o][a]?j=bb(a,b,c):(q||r)&&(j=Q(a))),"undefined"!=typeof j)break}return j||""===j||(j=A.interpolate(a,b),m&&!D&&(j=X(a,b))),j},H.versionInfo=function(){return F},H.loaderCache=function(){return s},H.directivePriority=function(){return B},H.statefulFilter=function(){return C},o&&(angular.equals(t,{})&&H.use(H.use()),g&&g.length))for(var db=function(a){return L(a.key,a.table),c.$emit("$translateChangeEnd",{language:a.key}),a},eb=0,fb=g.length;fb>eb;eb++){var gb=g[eb];(z||!t[gb])&&(G[gb]=S(gb).then(db))}return H}]}function d(a,b){"use strict";var c,d={},e="default";return d.setLocale=function(a){c=a},d.getInterpolationIdentifier=function(){return e},d.useSanitizeValueStrategy=function(a){return b.useStrategy(a),this},d.interpolate=function(c,d){d=d||{},d=b.sanitize(d,"params");var e=a(c)(d);return e=b.sanitize(e,"text")},d}function e(a,b,c,d,e,f){"use strict";var g=function(){return this.toString().replace(/^\s+|\s+$/g,"")};return{restrict:"AE",scope:!0,priority:a.directivePriority(),compile:function(b,h){var i=h.translateValues?h.translateValues:void 0,j=h.translateInterpolation?h.translateInterpolation:void 0,k=b[0].outerHTML.match(/translate-value-+/i),l="^(.*)("+c.startSymbol()+".*"+c.endSymbol()+")(.*)",m="^(.*)"+c.startSymbol()+"(.*)"+c.endSymbol()+"(.*)";return function(b,n,o){b.interpolateParams={},b.preText="",b.postText="";var p={},q=function(a,c,d){if(c.translateValues&&angular.extend(a,e(c.translateValues)(b.$parent)),k)for(var f in d)if(Object.prototype.hasOwnProperty.call(c,f)&&"translateValue"===f.substr(0,14)&&"translateValues"!==f){var g=angular.lowercase(f.substr(14,1))+f.substr(15);a[g]=d[f]}},r=function(a){if(angular.isFunction(r._unwatchOld)&&(r._unwatchOld(),r._unwatchOld=void 0),angular.equals(a,"")||!angular.isDefined(a)){var d=g.apply(n.text()).match(l);if(angular.isArray(d)){b.preText=d[1],b.postText=d[3],p.translate=c(d[2])(b.$parent);var e=n.text().match(m);angular.isArray(e)&&e[2]&&e[2].length&&(r._unwatchOld=b.$watch(e[2],function(a){p.translate=a,x()}))}else p.translate=n.text().replace(/^\s+|\s+$/g,"")}else p.translate=a;x()},s=function(a){o.$observe(a,function(b){p[a]=b,x()})};q(b.interpolateParams,o,h);var t=!0;o.$observe("translate",function(a){"undefined"==typeof a?r(""):""===a&&t||(p.translate=a,x()),t=!1});for(var u in o)o.hasOwnProperty(u)&&"translateAttr"===u.substr(0,13)&&s(u);if(o.$observe("translateDefault",function(a){b.defaultText=a}),i&&o.$observe("translateValues",function(a){a&&b.$parent.$watch(function(){angular.extend(b.interpolateParams,e(a)(b.$parent))})}),k){var v=function(a){o.$observe(a,function(c){var d=angular.lowercase(a.substr(14,1))+a.substr(15);b.interpolateParams[d]=c})};for(var w in o)Object.prototype.hasOwnProperty.call(o,w)&&"translateValue"===w.substr(0,14)&&"translateValues"!==w&&v(w)}var x=function(){for(var a in p)p.hasOwnProperty(a)&&void 0!==p[a]&&y(a,p[a],b,b.interpolateParams,b.defaultText)},y=function(b,c,d,e,f){c?a(c,e,j,f).then(function(a){z(a,d,!0,b)},function(a){z(a,d,!1,b)}):z(c,d,!1,b)},z=function(b,c,e,f){if("translate"===f){e||"undefined"==typeof c.defaultText||(b=c.defaultText),n.html(c.preText+b+c.postText);var g=a.isPostCompilingEnabled(),i="undefined"!=typeof h.translateCompile,j=i&&"false"!==h.translateCompile;(g&&!i||j)&&d(n.contents())(c)}else{e||"undefined"==typeof c.defaultText||(b=c.defaultText);var k=o.$attr[f];"data-"===k.substr(0,5)&&(k=k.substr(5)),k=k.substr(15),n.attr(k,b)}};(i||k||o.translateDefault)&&b.$watch("interpolateParams",x,!0);var A=f.$on("$translateChangeSuccess",x);n.text().length?r(o.translate?o.translate:""):o.translate&&r(o.translate),x(),b.$on("$destroy",A)}}}}function f(a,b){"use strict";return{compile:function(c){var d=function(){c.addClass(b.cloakClassName())},e=function(){c.removeClass(b.cloakClassName())},f=a.$on("$translateChangeEnd",function(){e(),f(),f=null});return d(),function(a,c,f){f.translateCloak&&f.translateCloak.length&&f.$observe("translateCloak",function(a){b(a).then(e,d)})}}}}function g(a,b){"use strict";var c=function(c,d,e){return angular.isObject(d)||(d=a(d)(this)),b.instant(c,d,e)};return b.statefulFilter()&&(c.$stateful=!0),c}function h(a){"use strict";return a("translations")}return angular.module("pascalprecht.translate",["ng"]).run(a),a.$inject=["$translate"],a.displayName="runTranslate",angular.module("pascalprecht.translate").provider("$translateSanitization",b),angular.module("pascalprecht.translate").constant("pascalprechtTranslateOverrider",{}).provider("$translate",c),c.$inject=["$STORAGE_KEY","$windowProvider","$translateSanitizationProvider","pascalprechtTranslateOverrider"],c.displayName="displayName",angular.module("pascalprecht.translate").factory("$translateDefaultInterpolation",d),d.$inject=["$interpolate","$translateSanitization"],d.displayName="$translateDefaultInterpolation",angular.module("pascalprecht.translate").constant("$STORAGE_KEY","NG_TRANSLATE_LANG_KEY"),angular.module("pascalprecht.translate").directive("translate",e),e.$inject=["$translate","$q","$interpolate","$compile","$parse","$rootScope"],e.displayName="translateDirective",angular.module("pascalprecht.translate").directive("translateCloak",f),f.$inject=["$rootScope","$translate"],f.displayName="translateCloakDirective",angular.module("pascalprecht.translate").filter("translate",g),g.$inject=["$parse","$translate"],g.displayName="translateFilterFactory",angular.module("pascalprecht.translate").factory("$translationCache",h),h.$inject=["$cacheFactory"],h.displayName="$translationCache","pascalprecht.translate"});
/*
 AngularJS v1.3.4
 (c) 2010-2014 Google, Inc. http://angularjs.org
 License: MIT
*/
(function(r,f,s){'use strict';f.module("ngMessages",[]).directive("ngMessages",["$compile","$animate","$templateRequest",function(q,k,l){return{restrict:"AE",controller:function(){this.$renderNgMessageClasses=f.noop;var b=[];this.registerMessage=function(d,a){for(var c=0;c<b.length;c++)if(b[c].type==a.type){if(d!=c){var g=b[d];b[d]=b[c];d<b.length?b[c]=g:b.splice(0,c)}return}b.splice(d,0,a)};this.renderMessages=function(d,a){d=d||{};var c;f.forEach(b,function(b){var e;if(e=!c||a)e=d[b.type],e=null!==
e&&!1!==e&&e;e?(b.attach(),c=!0):b.detach()});this.renderElementClasses(c)}},require:"ngMessages",link:function(b,d,a,c){c.renderElementClasses=function(b){b?k.setClass(d,"ng-active","ng-inactive"):k.setClass(d,"ng-inactive","ng-active")};var g=f.isString(a.ngMessagesMultiple)||f.isString(a.multiple),e;b.$watchCollection(a.ngMessages||a["for"],function(b){e=b;c.renderMessages(b,g)});(a=a.ngMessagesInclude||a.include)&&l(a).then(function(a){var h;a=f.element("<div/>").html(a);f.forEach(a.children(),
function(a){a=f.element(a);h?h.after(a):d.prepend(a);h=a;q(a)(b)});c.renderMessages(e,g)})}}}]).directive("ngMessage",["$animate",function(f){return{require:"^ngMessages",transclude:"element",terminal:!0,restrict:"AE",link:function(k,l,b,d,a){for(var c,g,e=l[0],n=e.parentNode,h=0,p=0;h<n.childNodes.length;h++){var m=n.childNodes[h];if(8==m.nodeType&&0<=m.nodeValue.indexOf("ngMessage")){if(m===e){c=p;break}p++}}d.registerMessage(c,{type:b.ngMessage||b.when,attach:function(){g||a(k,function(a){f.enter(a,
null,l);g=a})},detach:function(a){g&&(f.leave(g),g=null)}})}}}])})(window,window.angular);
//# sourceMappingURL=angular-messages.min.js.map

(function() {
    'use strict';

    var settingsApp = angular.module('oneKeyApp.settings', []);

    settingsApp.provider('appSettings',
        function() {
            return {
                getSettings: function(variable) {
                    if (!window.settings || !window.settings[variable]) {

                        throw new Error('Missing page variable: window.settings.' + variable);
                    }
                    return window.settings[variable];
                },
                $get: function() {
                    var allSettings = this.getSettings('appSettings');
                    return function(name) {
                        if (!angular.isDefined(allSettings[name])) {
                            throw new Error('App Setting Is Not Configured: ' + name);
                        }
                        return allSettings[name];
                    }
                }
            }

        });

}());

(function () {

    'use strict';

    angular
          .module('oneKeyApp')
        .service('authService', authService);

    authService.$inject = ['$state', 'angularAuth0', '$timeout', '$window', 'configSettings', 'userService'];

    function authService($state, angularAuth0, $timeout, $window, configSettings, userService) {
        const settings = configSettings.getSettings('appSettings');
        function login() {
            angularAuth0.authorize({
                connection: settings['auth0Connection']
            });
        }

        function handleAuthentication() {
            if (document.cookie.indexOf('Milwaukeetool_ApplicationCookie') === -1) {
                localStorage.removeItem('access_token');
                localStorage.removeItem('expires_at');
            }
            angularAuth0.parseHash({ hash: window.location.hash }, function (err, authResult) {
                if (authResult && authResult.accessToken) {
                    setSession(authResult).then(function () {
                        if ($window.location.href.includes('/Reports')) {
                            $window.location.href = '/Reports/Inventory';
                        } else {
                            $state.go('inventory');
                            $window.location.href = '/';
                        }
                    });
                } else if (!isAuthenticated()) {
                    login();
                } else if (err) {
                    $timeout(function () {
                        $state.go('inventory');
                    }, 0);
                    console.log(err);
                }
            });
        }

        function setSession(authResult) {
            // Set the time that the Access Token will expire at
            var expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
            localStorage.setItem('access_token', authResult.accessToken);
            localStorage.setItem('expires_at', expiresAt);
            document.cookie = handleCookie();

            return userService.setupUser(authResult.accessToken);
            
        }

        function logout() {
            // Remove tokens and expiry time from localStorage
            localStorage.removeItem('access_token');
            localStorage.removeItem('expires_at');
            document.cookie = handleCookie(true);

            $window.location.href = 'https://' + settings['auth0Domain'] + '/v2/logout?returnTo=' + $window.location.origin + '&client_id=' + settings['auth0ClientId'];
        }

        function isAuthenticated() {
            // Check whether the current time is past the 
            // Access Token's expiry time
            var expiresAt = JSON.parse(localStorage.getItem('expires_at'));
            return new Date().getTime() < expiresAt;
        }

        function handleCookie(expireCookie) {
            var cookieExpiration = '';
            var legacyCookie = '';
            var host = window.location.host;
            var subDomain = host.indexOf('.');
            var domain = host.substring(subDomain);
            if (domain.indexOf('milwaukeetool.eu') !== -1) {
                domain = '.milwaukeetool.eu';
            }
            if (domain.indexOf('milwaukeetools.com.au') !== -1) {
                domain = '.milwaukeetools.com.au';
            }

            if (expireCookie) {
                cookieExpiration = 'Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
                legacyCookie = ".AspNet.ApplicationCookie=; domain=" + domain + "; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT;";
            }
            return legacyCookie + 'Milwaukeetool_ApplicationCookie=loggedin=1;domain=' + domain + ';' + 'path=/;' + cookieExpiration;
        }

        return {
            login: login,
            handleAuthentication: handleAuthentication,
            logout: logout,
            isAuthenticated: isAuthenticated
        }
    }
})();

/*! nanoScrollerJS - v0.8.7 - (c) 2015 James Florentino; Licensed MIT */

!function (a) { return "function" == typeof define && define.amd ? define(["jquery"], function (b) { return a(b, window, document) }) : "object" == typeof exports ? module.exports = a(require("jquery"), window, document) : a(jQuery, window, document) }(function (a, b, c) { "use strict"; var d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, A, B, C, D, E, F, G, H; z = { paneClass: "nano-pane", sliderClass: "nano-slider", contentClass: "nano-content", enabledClass: "has-scrollbar", flashedClass: "flashed", activeClass: "active", iOSNativeScrolling: !1, preventPageScrolling: !1, disableResize: !1, alwaysVisible: !1, flashDelay: 1500, sliderMinHeight: 20, sliderMaxHeight: null, documentContext: null, windowContext: null }, u = "scrollbar", t = "scroll", l = "mousedown", m = "mouseenter", n = "mousemove", p = "mousewheel", o = "mouseup", s = "resize", h = "drag", i = "enter", w = "up", r = "panedown", f = "DOMMouseScroll", g = "down", x = "wheel", j = "keydown", k = "keyup", v = "touchmove", d = "Microsoft Internet Explorer" === b.navigator.appName && /msie 7./i.test(b.navigator.appVersion) && b.ActiveXObject, e = null, D = b.requestAnimationFrame, y = b.cancelAnimationFrame, F = c.createElement("div").style, H = function () { var a, b, c, d, e, f; for (d = ["t", "webkitT", "MozT", "msT", "OT"], a = e = 0, f = d.length; f > e; a = ++e) if (c = d[a], b = d[a] + "ransform", b in F) return d[a].substr(0, d[a].length - 1); return !1 }(), G = function (a) { return H === !1 ? !1 : "" === H ? a : H + a.charAt(0).toUpperCase() + a.substr(1) }, E = G("transform"), B = E !== !1, A = function () { var a, b, d; return a = c.createElement("div"), b = a.style, b.position = "absolute", b.width = "100px", b.height = "100px", b.overflow = t, b.top = "-9999px", c.body.appendChild(a), d = a.offsetWidth - a.clientWidth, c.body.removeChild(a), d }, C = function () { var a, c, d; return c = b.navigator.userAgent, (a = /(?=.+Mac OS X)(?=.+Firefox)/.test(c)) ? (d = /Firefox\/\d{2}\./.exec(c), d && (d = d[0].replace(/\D+/g, "")), a && +d > 23) : !1 }, q = function () { function j(d, f) { this.el = d, this.options = f, e || (e = A()), this.$el = a(this.el), this.doc = a(this.options.documentContext || c), this.win = a(this.options.windowContext || b), this.body = this.doc.find("body"), this.$content = this.$el.children("." + this.options.contentClass), this.$content.attr("tabindex", this.options.tabIndex || 0), this.content = this.$content[0], this.previousPosition = 0, this.options.iOSNativeScrolling && null != this.el.style.WebkitOverflowScrolling ? this.nativeScrolling() : this.generate(), this.createEvents(), this.addEvents(), this.reset() } return j.prototype.preventScrolling = function (a, b) { if (this.isActive) if (a.type === f) (b === g && a.originalEvent.detail > 0 || b === w && a.originalEvent.detail < 0) && a.preventDefault(); else if (a.type === p) { if (!a.originalEvent || !a.originalEvent.wheelDelta) return; (b === g && a.originalEvent.wheelDelta < 0 || b === w && a.originalEvent.wheelDelta > 0) && a.preventDefault() } }, j.prototype.nativeScrolling = function () { this.$content.css({ WebkitOverflowScrolling: "touch" }), this.iOSNativeScrolling = !0, this.isActive = !0 }, j.prototype.updateScrollValues = function () { var a, b; a = this.content, this.maxScrollTop = a.scrollHeight - a.clientHeight, this.prevScrollTop = this.contentScrollTop || 0, this.contentScrollTop = a.scrollTop, b = this.contentScrollTop > this.previousPosition ? "down" : this.contentScrollTop < this.previousPosition ? "up" : "same", this.previousPosition = this.contentScrollTop, "same" !== b && this.$el.trigger("update", { position: this.contentScrollTop, maximum: this.maxScrollTop, direction: b }), this.iOSNativeScrolling || (this.maxSliderTop = this.paneHeight - this.sliderHeight, this.sliderTop = 0 === this.maxScrollTop ? 0 : this.contentScrollTop * this.maxSliderTop / this.maxScrollTop) }, j.prototype.setOnScrollStyles = function () { var a; B ? (a = {}, a[E] = "translate(0, " + this.sliderTop + "px)") : a = { top: this.sliderTop }, D ? (y && this.scrollRAF && y(this.scrollRAF), this.scrollRAF = D(function (b) { return function () { return b.scrollRAF = null, b.slider.css(a) } }(this))) : this.slider.css(a) }, j.prototype.createEvents = function () { this.events = { down: function (a) { return function (b) { return a.isBeingDragged = !0, a.offsetY = b.pageY - a.slider.offset().top, a.slider.is(b.target) || (a.offsetY = 0), a.pane.addClass(a.options.activeClass), a.doc.bind(n, a.events[h]).bind(o, a.events[w]), a.body.bind(m, a.events[i]), !1 } }(this), drag: function (a) { return function (b) { return a.sliderY = b.pageY - a.$el.offset().top - a.paneTop - (a.offsetY || .5 * a.sliderHeight), a.scroll(), a.contentScrollTop >= a.maxScrollTop && a.prevScrollTop !== a.maxScrollTop ? a.$el.trigger("scrollend") : 0 === a.contentScrollTop && 0 !== a.prevScrollTop && a.$el.trigger("scrolltop"), !1 } }(this), up: function (a) { return function (b) { return a.isBeingDragged = !1, a.pane.removeClass(a.options.activeClass), a.doc.unbind(n, a.events[h]).unbind(o, a.events[w]), a.body.unbind(m, a.events[i]), !1 } }(this), resize: function (a) { return function (b) { a.reset() } }(this), panedown: function (a) { return function (b) { return a.sliderY = (b.offsetY || b.originalEvent.layerY) - .5 * a.sliderHeight, a.scroll(), a.events.down(b), !1 } }(this), scroll: function (a) { return function (b) { a.updateScrollValues(), a.isBeingDragged || (a.iOSNativeScrolling || (a.sliderY = a.sliderTop, a.setOnScrollStyles()), null != b && (a.contentScrollTop >= a.maxScrollTop ? (a.options.preventPageScrolling && a.preventScrolling(b, g), a.prevScrollTop !== a.maxScrollTop && a.$el.trigger("scrollend")) : 0 === a.contentScrollTop && (a.options.preventPageScrolling && a.preventScrolling(b, w), 0 !== a.prevScrollTop && a.$el.trigger("scrolltop")))) } }(this), wheel: function (a) { return function (b) { var c; if (null != b) return c = b.delta || b.wheelDelta || b.originalEvent && b.originalEvent.wheelDelta || -b.detail || b.originalEvent && -b.originalEvent.detail, c && (a.sliderY += -c / 3), a.scroll(), !1 } }(this), enter: function (a) { return function (b) { var c; if (a.isBeingDragged) return 1 !== (b.buttons || b.which) ? (c = a.events)[w].apply(c, arguments) : void 0 } }(this) } }, j.prototype.addEvents = function () { var a; this.removeEvents(), a = this.events, this.options.disableResize || this.win.bind(s, a[s]), this.iOSNativeScrolling || (this.slider.bind(l, a[g]), this.pane.bind(l, a[r]).bind("" + p + " " + f, a[x])), this.$content.bind("" + t + " " + p + " " + f + " " + v, a[t]) }, j.prototype.removeEvents = function () { var a; a = this.events, this.win.unbind(s, a[s]), this.iOSNativeScrolling || (this.slider.unbind(), this.pane.unbind()), this.$content.unbind("" + t + " " + p + " " + f + " " + v, a[t]) }, j.prototype.generate = function () { var a, c, d, f, g, h, i; return f = this.options, h = f.paneClass, i = f.sliderClass, a = f.contentClass, (g = this.$el.children("." + h)).length || g.children("." + i).length || this.$el.append('<div class="' + h + '"><div class="' + i + '" /></div>'), this.pane = this.$el.children("." + h), this.slider = this.pane.find("." + i), 0 === e && C() ? (d = b.getComputedStyle(this.content, null).getPropertyValue("padding-right").replace(/[^0-9.]+/g, ""), c = { right: -14, paddingRight: +d + 14 }) : e && (c = { right: -e }, this.$el.addClass(f.enabledClass)), null != c && this.$content.css(c), this }, j.prototype.restore = function () { this.stopped = !1, this.iOSNativeScrolling || this.pane.show(), this.addEvents() }, j.prototype.reset = function () { var a, b, c, f, g, h, i, j, k, l, m, n; return this.iOSNativeScrolling ? void (this.contentHeight = this.content.scrollHeight) : (this.$el.find("." + this.options.paneClass).length || this.generate().stop(), this.stopped && this.restore(), a = this.content, f = a.style, g = f.overflowY, d && this.$content.css({ height: this.$content.height() }), b = a.scrollHeight + e, l = parseInt(this.$el.css("max-height"), 10), l > 0 && (this.$el.height(""), this.$el.height(a.scrollHeight > l ? l : a.scrollHeight)), i = this.pane.outerHeight(!1), k = parseInt(this.pane.css("top"), 10), h = parseInt(this.pane.css("bottom"), 10), j = i + k + h, n = Math.round(j / b * i), n < this.options.sliderMinHeight ? n = this.options.sliderMinHeight : null != this.options.sliderMaxHeight && n > this.options.sliderMaxHeight && (n = this.options.sliderMaxHeight), g === t && f.overflowX !== t && (n += e), this.maxSliderTop = j - n, this.contentHeight = b, this.paneHeight = i, this.paneOuterHeight = j, this.sliderHeight = n, this.paneTop = k, this.slider.height(n), this.events.scroll(), this.pane.show(), this.isActive = !0, a.scrollHeight === a.clientHeight || this.pane.outerHeight(!0) >= a.scrollHeight && g !== t ? (this.pane.hide(), this.isActive = !1) : this.el.clientHeight === a.scrollHeight && g === t ? this.slider.hide() : this.slider.show(), this.pane.css({ opacity: this.options.alwaysVisible ? 1 : "", visibility: this.options.alwaysVisible ? "visible" : "" }), c = this.$content.css("position"), ("static" === c || "relative" === c) && (m = parseInt(this.$content.css("right"), 10), m && this.$content.css({ right: "", marginRight: m })), this) }, j.prototype.scroll = function () { return this.isActive ? (this.sliderY = Math.max(0, this.sliderY), this.sliderY = Math.min(this.maxSliderTop, this.sliderY), this.$content.scrollTop(this.maxScrollTop * this.sliderY / this.maxSliderTop), this.iOSNativeScrolling || (this.updateScrollValues(), this.setOnScrollStyles()), this) : void 0 }, j.prototype.scrollBottom = function (a) { return this.isActive ? (this.$content.scrollTop(this.contentHeight - this.$content.height() - a).trigger(p), this.stop().restore(), this) : void 0 }, j.prototype.scrollTop = function (a) { return this.isActive ? (this.$content.scrollTop(+a).trigger(p), this.stop().restore(), this) : void 0 }, j.prototype.scrollTo = function (a) { return this.isActive ? (this.scrollTop(this.$el.find(a).get(0).offsetTop), this) : void 0 }, j.prototype.stop = function () { return y && this.scrollRAF && (y(this.scrollRAF), this.scrollRAF = null), this.stopped = !0, this.removeEvents(), this.iOSNativeScrolling || this.pane.hide(), this }, j.prototype.destroy = function () { return this.stopped || this.stop(), !this.iOSNativeScrolling && this.pane.length && this.pane.remove(), d && this.$content.height(""), this.$content.removeAttr("tabindex"), this.$el.hasClass(this.options.enabledClass) && (this.$el.removeClass(this.options.enabledClass), this.$content.css({ right: "" })), this }, j.prototype.flash = function () { return !this.iOSNativeScrolling && this.isActive ? (this.reset(), this.pane.addClass(this.options.flashedClass), setTimeout(function (a) { return function () { a.pane.removeClass(a.options.flashedClass) } }(this), this.options.flashDelay), this) : void 0 }, j }(), a.fn.nanoScroller = function (b) { return this.each(function () { var c, d; if ((d = this.nanoscroller) || (c = a.extend({}, z, b), this.nanoscroller = d = new q(this, c)), b && "object" == typeof b) { if (a.extend(d.options, b), null != b.scrollBottom) return d.scrollBottom(b.scrollBottom); if (null != b.scrollTop) return d.scrollTop(b.scrollTop); if (b.scrollTo) return d.scrollTo(b.scrollTo); if ("bottom" === b.scroll) return d.scrollBottom(0); if ("top" === b.scroll) return d.scrollTop(0); if (b.scroll && b.scroll instanceof a) return d.scrollTo(b.scroll); if (b.stop) return d.stop(); if (b.destroy) return d.destroy(); if (b.flash) return d.flash() } return d.reset() }) }, a.fn.nanoScroller.Constructor = q });
//# sourceMappingURL=jquery.nanoscroller.min.js.map
