{"version":3,"sources":["jsdelivr-header.js","/gh/john-oc/acute-select@master/acute/acute.select/acute.select.js"],"names":[],"mappings":"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","file":"/gh/john-oc/acute-select@master/acute/acute.select/acute.select.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /gh/john-oc/acute-select@master/acute/acute.select/acute.select.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","﻿/// <reference path=\"../lib/angular.1.2.1.js\" />\n\n// Directive that creates a searchable dropdown list.\n\n// Associated attributes:-\n// ac-model - use instead of ng-model\n// ac-options - use instead of ng-options.\n\n// Example:- <select class=\"ac-select\" ac-model=\"colour\" ac-options=\"c.name for c in colours\"></select>\n\n// Note:- ac-options works like ng-options, but does not support option groups\n\nangular.module(\"acute.select\", [])\n.directive(\"acSelect\", function($parse, acuteSelectService) {\n    var defaultSettings = acuteSelectService.getSettings();\n    return {\n        restrict: \"EAC\",\n        scope: {\n            \"acSettings\": \"@\",\n            \"acOptions\": \"@\",\n            \"model\": \"=acModel\",\n            \"acChange\": \"&\",\n            \"keyField\": \"@acKey\",\n            \"acRefresh\": \"=\",\n            \"acFocusWhen\": \"=\",\n            \"id\": \"@\"\n        },\n        replace: true,\n        templateUrl: defaultSettings.templatePath + \"acute.select.htm\",\n        link: function(scope, element, attrs) {\n            scope.initialise();\n        },\n        // **************************************************************\n        //                          CONTROLLER\n        // **************************************************************\n        controller: function($scope, $element, $window, $rootScope, $timeout, $filter, navKey, safeApply) {\n\n            var dataFunctionFiltering = false;\n\n            $scope.initialise = function() {\n                $scope.settings = acuteSelectService.getSettings();\n                $scope.previousSearchText = \"\";\n                $scope.searchText = \"\";\n                $scope.longestText = \"\";\n                $scope.comboText = \"\";\n                $scope.items = [];\n                $scope.allItems = [];        // Unfiltered\n                $scope.selectedItem = null;\n                $scope.allDataLoaded = false;\n                $scope.scrollTo = 0;         // To change scroll position\n                $scope.scrollPosition = 0;   // Reported scroll position\n                $scope.listHeight = 0;\n                $scope.matchFound = false;\n\n                // Check that ac-options and ac-model values are set\n                if (!$scope.acOptions || $scope.model === undefined) {\n                    throw \"ac-options and ac-model attributes must be set\";\n                }\n\n                processSettings();\n\n                // Parse acOptions\n\n                // Value should be in the form \"label for value in array\" or \"for value in array\"\n                var words = $scope.acOptions.split(' ');\n                var len = words.length;\n                $scope.textField = null;\n                $scope.dataFunction = null;\n\n                // Save initial selection, if any\n                $scope.setInitialSelection();\n\n                if (len > 3) {\n                    if (len > 4) {\n                        var label = words[len - 5];     // E.g. colour.name\n                        $scope.textField = label.split(\".\")[1];\n                    }\n                    var dataName = words[len - 1];\n\n                    // See if a data load function is specified, i.e. name ends in \"()\"\n                    if (dataName.indexOf(\"()\") === dataName.length - 2) {\n                        dataName = dataName.substr(0, dataName.length - 2);\n                        // Get a reference to the data function\n                        var dataFunction = $scope.$parent.$eval(dataName);\n                        if (typeof dataFunction === \"function\") {\n                            $scope.dataFunction = dataFunction;\n\n                            // See if data function accepts search filter text\n                            dataFunctionFiltering = ($scope.dataFunction.length >= 2);\n\n                            if ($scope.settings.loadOnCreate) {\n                                // Load initial data (args are callback function, search text, item offset and filter type)\n                                $scope.dataFunction($scope.dataCallback, \"\", 0, $scope.settings.filterType);\n                            }\n                        }\n                        else {\n                            throw \"Invalid data function: \" + dataName;\n                        }\n                    }\n                    else {\n                        // Get the data from the parent $scope\n                        var dataItems = $scope.$parent.$eval(dataName);\n                        // Create dropdown items\n                        $scope.loadItems(dataItems, $scope.model);\n                        // Save selected item\n                        $scope.confirmedItem = angular.copy($scope.selectedItem);\n                        $scope.allDataLoaded = true;\n                    }\n                }\n            };\n\n            $scope.filterTypeChange = function() {\n                if (dataFunctionFiltering) {\n                    $scope.allDataLoaded = false;\n                }\n                $scope.filterData();\n                giveFocusToTextbox();\n            };\n\n            // If the ac-refresh attribute is set, watch it. If its value gets set to true, re-initialise.\n            if ($scope.acRefresh !== undefined) {\n                $scope.$watch(\"acRefresh\", function(newValue, oldValue) {\n                    if (newValue === true && newValue !== oldValue) {\n                        $scope.initialise();\n                    }\n                });\n            }\n\n            // Handle ac-focus-when attribute. When set to true\n            // give focus to either the combo or search text box\n            if ($scope.acFocusWhen !== undefined) {\n                $scope.$watch(\"acFocusWhen\", function(newValue, oldValue) {\n                    if (newValue === true && newValue !== oldValue) {\n                        $scope.acFocusWhen = false;\n                        giveFocusToTextbox();\n                    }\n                });\n            }\n\n            function giveFocusToTextbox() {\n                // Set flag to fire the ac-focus directive\n                if ($scope.settings.comboMode) {\n                    $scope.comboFocus = true;\n                }\n                else {\n                    $scope.searchBoxFocus = true;\n                }\n            }\n\n            $scope.setInitialSelection = function() {\n                if ($scope.model) {\n                    $scope.initialSelection = angular.copy($scope.model);\n                    $scope.initialItem = $scope.getItemFromDataItem($scope.model, 0);\n                    $scope.confirmedItem = $scope.selectedItem = $scope.initialItem;\n                    $scope.comboText = $scope.confirmedItem ? $scope.confirmedItem.text : \"\";\n                }\n            };\n\n            // Create dropdown items based on the source data items\n            $scope.loadItems = function(dataItems, selectedDataItem) {\n                var itemCount, itemIndex, item, key = $scope.keyField;\n\n                if (angular.isArray(dataItems)) {\n\n                    var foundSelected = false;\n                    itemCount = $scope.items.length;\n\n                    angular.forEach(dataItems, function(dataItem, index) {\n                        itemIndex = itemCount + index;\n                        item = $scope.getItemFromDataItem(dataItem, itemIndex);\n                        if (item) {\n                            $scope.items.push(item);\n                            // If not currently filtering\n                            if (!$scope.searchText) {\n                                // Look for a matching item\n                                if (dataItem === selectedDataItem || (key && selectedDataItem && dataItem[key] == selectedDataItem[key])) {\n                                    confirmSelection(item);\n                                    foundSelected = true;\n                                }\n                            }\n                            else if ($scope.searchText.toLowerCase() === item.text.toLowerCase()) {\n                                // Search text matches item\n                                $scope.selectedItem = item;\n                            }\n\n                            if (item.text.length > $scope.longestText.length) {\n                                if ($scope.maxCharacters && item.text.length > $scope.maxCharacters) {\n                                    $scope.longestText = item.text.substr(0, $scope.maxCharacters);\n                                }\n                                else {\n                                    $scope.longestText = item.text;\n                                }\n                            }\n                        }\n                    });\n\n                    // If not currently filtering and there's no selected item, but we have an initial selection\n                    if (!$scope.searchText && $scope.initialSelection && !foundSelected) {\n                        // Create a new item\n                        item = $scope.getItemFromDataItem($scope.initialSelection, 0);\n                        if (item) {\n                            // Add it to the start of the items array\n                            $scope.items.unshift(item);\n                            // Update indexes\n                            angular.forEach($scope.items, function(item, index) {\n                                item.index = index;\n                            });\n\n                            confirmSelection(item);\n                        }\n                    }\n\n                    // If data is not filtered\n                    if (!$scope.searchText) {\n                        angular.copy($scope.items, $scope.allItems);\n                    }\n\n                    $scope.setListHeight();\n\n                    checkItemCount($scope.items);\n                }\n            };\n\n            function processSettings() {\n                if ($scope.acSettings) {\n                    var settings = $scope.$eval($scope.acSettings);\n                    if (typeof settings === \"object\") {\n                        // Merge settings with default values\n                        angular.extend($scope.settings, settings);\n                    }\n                }\n                $scope.longestText = $scope.settings.placeholderText;\n\n                $scope.maxTextWidth = \"\";\n\n                // If maxWidth is set, limit textbox size, allowing room for dropdown icon\n                if ($scope.settings.maxWidth) {\n                    var maxWidth = parseInt($scope.settings.maxWidth);\n                    // Set an approximate limit to the number of characters to allow in $scope.longestText\n                    $scope.maxCharacters = Math.round(maxWidth / 6);\n                    $scope.maxTextWidth = (maxWidth - 100) + \"px\";\n                }\n\n                // Pop-up needs position:absolute *unless* entire component is being positioned absolutely, in which we need to change it to \"static\"\n                var popUpPosition = $scope.settings.positionAbsolute ? \"static\" : \"absolute\";\n                $scope.popupStyles = {\n                    \"minWidth\": $scope.settings.minWidth,\n                    \"position\": popUpPosition\n                };\n\n                if ($scope.settings.showFilterOptions) {\n                    // Min width must be at least 200px to accommodate the filter options\n                    var minWidth = parseInt($scope.settings.minWidth);\n                    if (isNaN(minWidth) || minWidth < 220) {\n                        $scope.settings.minWidth = \"220px\";\n                    }\n                }\n            }\n\n            function checkItemCount() {\n                $scope.noItemsFound = $scope.items.length === 0;\n                $scope.showAddMessage = false;\n                //GC: If no item is found clear the selected item\n                if ($scope.noItemsFound) {\n                    $scope.selectedItem = null;\n                }\n\n                // If in combo mode and can add custom values\n                if ($scope.settings.comboMode && $scope.comboText && $scope.settings.allowCustomText) {\n                    // If combo text doesn't match the current selected item text, show message to add.\n                    var selectedText = $scope.selectedItem ? $scope.selectedItem.text : \"\";\n\n                    if ($scope.comboText != selectedText) {\n                        $scope.showAddMessage = true;\n                    }\n                }\n            }\n\n            $scope.getItemFromDataItem = function(dataItem, itemIndex) {\n                var item = null;\n                if (dataItem !== null) {\n                    if ($scope.textField === null && typeof dataItem === 'string') {\n                        item = { \"text\": dataItem, \"value\": dataItem, \"index\": itemIndex };\n                    }\n                    else if (dataItem[$scope.textField]) {\n                        item = { \"text\": dataItem[$scope.textField], \"value\": dataItem, \"index\": itemIndex };\n                    }\n                }\n                return item;\n            };\n\n            // Set height of list according to number of visible items\n            $scope.setListHeight = function() {\n                var itemCount = $scope.items.length;\n                if (itemCount > $scope.settings.itemsInView) {\n                    itemCount = $scope.settings.itemsInView;\n                }\n\n                $scope.listHeight = $scope.settings.itemHeight * itemCount;\n            };\n\n            $scope.$watch(\"model\", function(newValue, oldValue) {\n                if (newValue != oldValue) {\n                    if ($scope.modelUpdating) {\n                        $scope.modelUpdating = false;\n                    }\n                    else if (!newValue && !oldValue) {\n                        // Do nothing\n                    }\n                    else if (newValue && !oldValue) {\n                        // Model no longer null\n                        $scope.setInitialSelection();\n                    }\n                    else if (oldValue && !newValue) {\n                        // Model cleared\n                        $scope.setInitialSelection();\n                    }\n                    else {\n                        // Check that the text is different\n                        if (!$scope.textField || newValue[$scope.textField] !== oldValue[$scope.textField]) {\n                            // Model has been changed in the parent scope\n                            $scope.setInitialSelection();\n                        }\n                    }\n                }\n            });\n\n            if ($scope.selectedItem) {\n                $scope.comboText = $scope.selectedItem.text;\n            }\n\n            // Close all instances when user clicks elsewhere\n            $window.onclick = function(event) {\n                closeWhenClickingElsewhere(event, function() {\n                    $scope.sentBroadcast = false;\n                    $rootScope.$broadcast(\"ac-select-close-all\");\n                });\n            };\n\n            // Keyboard events\n            $scope.keyHandler = function(event) {\n\n                if (!$scope.settings.showSearchBox) {\n                    handleCharCodes(event);\n                }\n\n                var keyCode = event.which || event.keyCode;\n\n                if (keyCode === navKey.downArrow) {\n                    $scope.popupVisible = true;\n                }\n\n                if (keyCode === navKey.leftArrow || keyCode === navKey.rightArrow) {\n                    event.stopPropagation();\n                }\n                else if ($scope.popupVisible || keyCode === navKey.del) {\n                    var stopPropagation = true;\n                    switch (keyCode) {\n                        case navKey.downArrow:\n                            downArrowKey();\n                            break;\n                        case navKey.upArrow:\n                            upArrowKey();\n                            break;\n                        case navKey.enter:\n                            enterKey();\n                            break;\n                        case navKey.end:\n                            endKey();\n                            break;\n                        case navKey.home:\n                            homeKey();\n                            break;\n                        case navKey.escape:\n                            escapeKey();\n                            break;\n                        case navKey.del:\n                            deleteKey(event);\n                            break;\n                        case navKey.pageUp:\n                            pageUpKey();\n                            break;\n                        case navKey.pageDown:\n                            pageDownKey();\n                            break;\n                        default:\n                            stopPropagation = false;\n                            break;\n                    }\n\n                    if (stopPropagation) event.stopPropagation();\n                }\n            };\n\n            // For the combo text box, handle the enter key, which can be used to add a new custom value\n            $scope.comboKeyHandler = function(event) {\n                var keyCode = event.which || event.keyCode;\n                if (keyCode === navKey.enter) {\n                    if (customAddRequest()) {\n                        confirmSelection(null);\n                    }\n                }\n            };\n\n            function handleCharCodes(event) {\n                var character, i, item;\n                if (event.keyCode) {\n                    character = String.fromCharCode(event.keyCode);\n                    for (i = 0; i < $scope.items.length; i++) {\n                        item = $scope.items[i];\n                        if (item.text.length > 0 && item.text.substr(0, 1).toUpperCase() === character) {\n                            $scope.selectedItem = item;\n                        }\n                    }\n                }\n            }\n\n            // Callback function to receive async data\n            $scope.dataCallback = function(data, searchText, offset) {\n\n                // Quit if search text has changed since the data function was called\n                if (searchText !== undefined && searchText !== $scope.searchText) {\n                    return;\n                }\n\n                var selectedDataItem = null;\n\n                $scope.dataItems = data;\n\n                // If we have a selected item, get its value\n                if ($scope.selectedItem !== null) {\n                    selectedDataItem = $scope.selectedItem.value;\n                }\n                else {\n                    selectedDataItem = $scope.model;\n                }\n\n                // Clear all existing items, unless offset > 0, i.e. we're paging and getting additional items\n                if (!offset || offset == 0) {\n                    $scope.items = [];\n                }\n\n                $scope.loadItems(data, selectedDataItem);\n\n                // If not in paging mode\n                if (!$scope.settings.pageSize) {\n                    // All data is now loaded\n                    $scope.allDataLoaded = true;\n                    // Clear loadOnOpen flag to avoid re-loading when dropdown is next opened\n                    $scope.settings.loadOnOpen = false;\n                }\n                else {\n\n                    // All data is loaded if fewer than [pageSize] items were returned\n                    $scope.allDataLoaded = data.length < $scope.settings.pageSize;\n\n                    // If user was scrolling down\n                    if ($scope.requestedItemIndex) {\n                        // Select first of the newly loaded items (if present)\n                        if ($scope.requestedItemIndex < $scope.items.length) {\n                            $scope.selectedItem = $scope.items[$scope.requestedItemIndex];\n                            ensureItemVisible($scope.selectedItem);\n                        }\n                        $scope.requestedItemIndex = null;\n                    }\n                }\n\n                if ($scope.allDataLoaded) {\n                    $scope.previousSearchText = $scope.searchText;\n                }\n\n                $scope.loading = false;\n                $scope.loadMessage = \"Load more...\";\n\n            };\n\n            $scope.comboTextChange = function() {\n                $scope.popupVisible = true;\n                $scope.ensureDataLoaded();\n                $scope.searchText = $scope.comboText;\n                if ($scope.comboText == '' && $scope.settings.allowClear) {\n                    clearSelection();\n                }\n\n                $scope.filterData();\n            };\n\n            // Show/hide popup\n            $scope.togglePopup = function() {\n                $scope.popupVisible = !$scope.popupVisible;\n                if ($scope.popupVisible) {\n                    // Pop-up opening\n                    if ($scope.settings.comboMode) {\n                        $timeout(function() { $scope.comboFocus = true; });\n                    }\n                    else {\n                        $timeout(function() { $scope.searchBoxFocus = true; });\n                    }\n                    $scope.ensureDataLoaded();\n                    clearClientFilter();\n                }\n            };\n\n            $scope.ensureDataLoaded = function() {\n                if (!$scope.allDataLoaded && $scope.dataFunction && $scope.settings.loadOnOpen) {\n                    // Load initial data (args are callback function, search text, item offset and filter type)\n                    $scope.dataFunction($scope.dataCallback, \"\", 0, $scope.settings.filterType);\n                }\n            };\n\n            // When clicking on the ac-select-main div\n            $scope.mainClick = function() {\n                // Close any other ac-select instances\n                $scope.sentBroadcast = true;\n                $rootScope.$broadcast(\"ac-select-close-all\");\n            };\n\n            $scope.$on(\"ac-select-close-all\", function() {\n                if (!$scope.sentBroadcast && $scope.popupVisible) {\n                    $scope.popupVisible = false;\n                    safeApply($scope);\n                    // If clear is not allowed and we're in combo mode\n                    if (!$scope.settings.allowClear && $scope.settings.comboMode && $scope.selectedItem) {\n                        // Update the combo text to reflect the currently selected item\n                        $scope.comboText = $scope.confirmedItem.text;\n                    }\n                }\n                else {\n                    $scope.sentBroadcast = false;\n                }\n            });\n\n            $scope.itemClick = function(i) {\n                confirmSelection($scope.items[i]);\n            };\n\n            $scope.getItemClass = function(i) {\n                if ($scope.selectedItem && $scope.items[i].value === $scope.selectedItem.value) {\n                    return \"ac-select-highlight\";\n                }\n                else {\n                    return \"\";\n                }\n            };\n\n            $scope.addButtonClick = function() {\n                if (customAddRequest()) {\n                    confirmSelection(null);\n                }\n            };\n\n            $scope.listScrolled = function(scrollPosition) {\n                $scope.scrollPosition = scrollPosition;\n                if ($scope.settings.pageSize) {\n                    var totalHeight = $scope.items.length * $scope.settings.itemHeight;\n                    // If scrolled past the last item\n                    if (scrollPosition > totalHeight - $scope.listHeight) {\n                        $scope.loadMore();\n                    }\n                }\n            };\n\n            // Load further data when paging is enabled\n            $scope.loadMore = function() {\n                if (!$scope.loading) {\n                    $scope.loading = true;\n                    $scope.loadMessage = \"Loading...\";\n\n                    var offSet = $scope.items.length;\n                    $scope.dataFunction($scope.dataCallback, $scope.searchText, offSet, $scope.settings.filterType);\n                }\n            };\n\n            // Private functions\n\n            function confirmSelection(item, forceClose) {\n\n                $scope.selectedItem = item;\n\n                var oldConfirmedItem = $scope.confirmedItem;\n                var close = false;\n                if ($scope.selectedItem) {\n                    $scope.confirmedItem = angular.copy($scope.selectedItem);\n                    $scope.modelUpdating = true;\n                    $scope.model = $scope.selectedItem.value;\n                    $scope.comboText = $scope.selectedItem.text;\n                    close = true;\n                }\n                else {\n                    // Try adding as a custom item\n                    if (customAddRequest()) {\n                        close = true;\n                    }\n                }\n\n                // If the pop-up is visible (i.e. not setting an initial selection)\n                if ($scope.popupVisible) {\n                    fireChangeEvent();\n                }\n\n                // Clear any initial selection                \n                $scope.initialSelection = null;\n                $scope.initialItem == null;\n\n                if ($scope.popupVisible && (close || forceClose)) {\n                    $scope.popupVisible = false;\n                    $scope.wrapperFocus = true;\n                    // If all data is loaded\n                    if ((!dataFunctionFiltering || $scope.allDataLoaded) && !$scope.settings.comboMode) {\n                        // Clear the search text and filter\n                        $scope.searchText = \"\";\n                        clearClientFilter();\n                    }\n                }                \n            }\n\n            function fireChangeEvent() {\n                // Fire acChange function, if specified\n                if (typeof $scope.acChange === 'function') {\n                    $scope.acChange({ value: $scope.selectedItem ? $scope.selectedItem.value : null });\n                }\n            }\n\n            function customAddRequest() {\n                var customText, dataItem, selectedText;\n                var added = false;\n                if ($scope.settings.allowCustomText && $scope.showAddMessage) {\n                    customText = $scope.settings.comboMode ? $scope.comboText : $scope.searchText;\n                    selectedText = $scope.selectedItem ? $scope.selectedItem.text : \"\";\n                    if (customText.length > 0 && customText !== selectedText) {\n                        // Create new data item\n                        dataItem = {};\n                        dataItem[$scope.textField] = customText;\n\n                        // add the key field if it is defined.\n                        if ($scope.keyField) {\n                            dataItem[$scope.keyField] = customText;\n                        }\n                        $scope.modelUpdating = true;\n                        $scope.model = dataItem;\n                        $scope.confirmedItem = $scope.selectedItem = { \"text\": customText, \"value\": dataItem, \"index\": -1 };\n                        $scope.items.push($scope.selectedItem);\n                        $scope.allItems.push($scope.selectedItem);\n                        added = true;\n                    }\n                }\n                return added;\n            }\n\n            function enterKey() {\n                if ($scope.popupVisible) {\n                    confirmSelection($scope.selectedItem);\n                }\n            }\n\n            function downArrowKey() {\n                if ($scope.items.length > 0) {\n                    var selected = false;\n                    if ($scope.selectedItem) {\n                        var newIndex = $scope.selectedItem.index + 1;\n                        if (newIndex < $scope.items.length) {\n                            var targetItem = $scope.items[newIndex];\n                            $scope.selectedItem = targetItem;\n                            ensureItemVisible($scope.selectedItem);\n                            selected = true;\n                        }\n                        else if ($scope.settings.pageSize && $scope.items.length >= $scope.settings.pageSize) {\n                            $scope.requestedItemIndex = newIndex;\n                            $scope.scrollTo += $scope.settings.itemHeight;\n                            $scope.loadMore();\n                        }\n                    }\n                    else {\n                        // Select first item\n                        $scope.selectedItem = $scope.items[0];\n                        selected = true;\n                    }\n                }\n            }\n\n            function upArrowKey() {\n                if ($scope.items.length > 0) {\n                    if ($scope.selectedItem) {\n                        var targetItem = $scope.items[$scope.selectedItem.index - 1];\n                        if (targetItem) {\n                            $scope.selectedItem = targetItem;\n                            ensureItemVisible($scope.selectedItem);\n                        }\n                    }\n                    else {\n                        if ($scope.settings.comboMode) {\n                            $scope.comboFocus = true;\n                        }\n                        else {\n                            $scope.searchBoxFocus = true;\n                        }\n                    }\n                }\n            }\n\n            function pageUpKey() {\n                if ($scope.items.length > 0 && $scope.selectedItem) {\n                    var newIndex = $scope.selectedItem.index - $scope.settings.itemsInView;\n                    if (newIndex < 0) newIndex = 0;\n                    var targetItem = $scope.items[newIndex];\n                    if (targetItem) {\n                        $scope.selectedItem = targetItem;\n                        ensureItemVisible($scope.selectedItem);\n                    }\n                }\n            }\n\n            function pageDownKey() {\n                var newIndex;\n                if ($scope.items.length > 0) {\n                    if ($scope.selectedItem) {\n                        newIndex = $scope.selectedItem.index + $scope.settings.itemsInView;\n                    }\n                    else {\n                        newIndex = $scope.settings.itemsInView - 1;\n                    }\n                    // If past the end\n                    if (newIndex >= $scope.items.length) {\n                        if ($scope.allDataLoaded) {\n                            newIndex = $scope.items.length - 1;\n                        }\n                        else {\n\n                        }\n                    }\n                    var targetItem = $scope.items[newIndex];\n                    if (targetItem) {\n                        $scope.selectedItem = targetItem;\n                        ensureItemVisible($scope.selectedItem);\n                    }\n                }\n            }\n\n            function endKey() {\n                if ($scope.items.length > 0) {\n                    $scope.selectedItem = $scope.items[$scope.items.length - 1];\n                    var totalHeight = $scope.settings.itemHeight * $scope.items.length;\n                    $scope.scrollTo = totalHeight - $scope.listHeight;\n                }\n            }\n\n            function homeKey() {\n                if ($scope.items.length > 0) {\n                    $scope.selectedItem = $scope.items[0];\n                    $scope.scrollTo = 0;\n                }\n            }\n\n            function escapeKey() {\n                // Revert to last confirmed selection\n                $scope.selectedItem = $scope.confirmedItem;\n                confirmSelection($scope.selectedItem, true);\n            }\n\n            function deleteKey(event) {\n                if ($scope.settings.allowClear) {\n                    var srcElement = angular.element(event.target);\n                    // If in combo textbox, ignore\n                    if (srcElement.hasClass('ac-select-text')) {\n                        event.stopPropagation();\n                    }\n                    else {\n                        clearSelection();\n                    }\n                }\n            }\n\n            function clearSelection() {\n                var oldConfirmedItem = $scope.confirmedItem;\n                $scope.selectedItem = null;\n                $scope.confirmedItem = null;\n                $scope.modelUpdating = true;\n                $scope.model = null;\n                $scope.initialSelection = null;\n                $scope.scrollTo = 0;\n                $scope.comboText = \"\";\n\n                if (oldConfirmedItem !== null) {\n                    fireChangeEvent();\n                }\n            }\n\n            function ensureItemVisible(item) {\n                var itemHeight = $scope.settings.itemHeight;\n                var itemTop = itemHeight * item.index;\n                if (itemTop + itemHeight > $scope.listHeight + $scope.scrollPosition) {\n                    $scope.scrollTo = itemTop + itemHeight - $scope.listHeight;\n                }\n                else if (itemTop < $scope.scrollPosition) {\n                    $scope.scrollTo = itemTop;\n                }\n            }\n\n            $scope.filterData = function() {\n\n                var itemCount = $scope.allItems.length;\n\n                if (dataFunctionFiltering) {\n                    // If search text is blank OR paging is enabled && current number of items is >= pageSize (or zero)\n                    if ($scope.searchText === \"\" || ($scope.settings.pageSize && (itemCount >= $scope.settings.pageSize || itemCount === 0))) {\n                        // Data needs to be re-loaded.\n                        $scope.allDataLoaded = false;\n                    }\n                }\n\n                if ($scope.allDataLoaded) {\n\n                    var itemsToFilter = $scope.allItems;\n\n                    // If search text includes the previous search\n                    if ($scope.previousSearchText && $scope.searchText.indexOf($scope.previousSearchText) != -1) {\n                        // We can refine the filtering, without checking all items\n                        itemsToFilter = $scope.items;\n                    }\n\n                    if ($scope.settings.filterType == \"contains\") {\n                        $scope.items = $filter(\"filter\")(itemsToFilter, function(item) {\n                            // Check for match at start of items only\n                            return item.text.toLowerCase().indexOf($scope.searchText.toLowerCase()) > -1;\n                        });\n                    }\n                    else {\n                        $scope.items = $filter(\"filter\")(itemsToFilter, function(item) {\n                            // Check for match at start of items only\n                            return item.text.substr(0, $scope.searchText.length).toLowerCase() === $scope.searchText.toLowerCase();\n                        });\n                    }\n                    // Update indexes\n                    angular.forEach($scope.items, function(item, index) {\n                        item.index = index;\n                    });\n\n                    checkItemCount();\n                }\n                else {\n                    // Pass search text to data function(if it accepts filter search text)\n                    if (dataFunctionFiltering) {\n                        // If search text has enough chars (or it's just been cleared)\n                        if ($scope.searchText.length >= $scope.settings.minSearchLength || $scope.searchText == \"\") {\n                            // Get data\n                            $scope.dataFunction($scope.dataCallback, $scope.searchText, 0, $scope.settings.filterType);\n                        }\n                    }\n                    else if ($scope.searchText === \"\") {\n                        // Clear filter\n                        clearClientFilter();\n                    }\n                }\n\n                // If narrowed down to one item (and search text isn't a subset of the previous search), select it\n                if ($scope.items.length === 1 && $scope.previousSearchText.indexOf($scope.searchText) === -1) {\n                    $scope.matchFound = true;\n                    $scope.selectedItem = $scope.items[0];\n                }\n                else {\n                    // See if the search text exactly matches one of the items\n                    $scope.matchFound = searchTextMatchesItem();\n                    if ($scope.matchFound) {\n                        $scope.showAddMessage = false;\n                    }\n                }\n\n                $scope.previousSearchText = $scope.searchText;\n                $scope.setListHeight();\n            };\n\n            // Look for an item with text that exactly matches the search text\n            function searchTextMatchesItem() {\n                var i, valid = false;\n                if ($scope.searchText.length > 0) {\n                    for (i = 0; i < $scope.items.length; i++) {\n                        if ($scope.searchText.toLowerCase() === $scope.items[i].text.toLowerCase()) {\n                            $scope.selectedItem = $scope.items[i];\n                            $scope.searchText = $scope.comboText = $scope.selectedItem.text;\n                            valid = true;\n                            break;\n                        }\n                    }\n                }\n                return valid;\n            }\n\n            // Remove any client filtering of items\n            function clearClientFilter() {\n                if ($scope.dataFunction === null || $scope.allDataLoaded) {\n                    $scope.items = $scope.allItems;\n                    $scope.setListHeight();\n                }\n            }\n\n            function closeWhenClickingElsewhere(event, callbackFn) {\n\n                var element = event.target;\n                if (!element) return;\n\n                var clickedOnPopup = false;\n                // Check up to 10 levels up the DOM tree\n                for (var i = 0; i < 10 && element && !clickedOnPopup; i++) {\n                    if (angular.element(element).hasClass('ac-select-wrapper')) {\n                        clickedOnPopup = true;\n                    }\n                    else {\n                        element = element.parentElement;\n                    }\n                }\n\n                if (!clickedOnPopup) {\n                    callbackFn();\n                }\n            }\n\n            function log(text) {\n                if (console && console.log && $scope.settings.debug) {\n                    console.log(\"ac-select:- \" + text);\n                }\n            }\n        }\n    };\n})\n\n// Directive to set focus to an element when a specified expression is true\n.directive('acFocus', function($timeout, $parse, safeApply) {\n    return {\n        restrict: \"A\",\n        link: function(scope, element, attributes) {\n            var setFocus = $parse(attributes.acFocus);\n            scope.$watch(setFocus, function(newValue, oldValue) {\n                if (newValue === true && newValue != oldValue) {\n                    $timeout(function() {\n                        element[0].focus();\n                    }, 100);\n                }\n            });\n            // Set the \"setFocus\" attribute value to 'false' on blur event\n            // using the \"assign\" method on the function that $parse returns\n            element.bind('blur', function() {\n                safeApply(scope, function() { setFocus.assign(scope, false) });\n            });\n        }\n    };\n})\n\n.directive('acSelectOnFocus', function() {\n    return {\n        restrict: 'A',\n        scope: {\n            acSelectOnFocus: \"=\"\n        },\n        link: function(scope, element, attrs) {\n            element.bind('focus', function() {\n                if (scope.acSelectOnFocus !== false && scope.acSelectOnFocus !== 'false') {\n                    element[0].select();\n                }\n            });\n        }\n    };\n})\n\n// Directive for a scroll container. Set the \"ac-scroll-to\" attribute to an expression and when its value changes,\n// the div will scroll to that position\n.directive('acScrollTo', function() {\n    return {\n        restrict: \"A\",\n        scope: false,\n        controller: function($scope, $element, $attrs) {\n            var expression = $attrs.acScrollTo;\n            $scope.$watch(expression, function(newValue, oldValue) {\n                if (newValue != oldValue) {\n                    var scrollTop = $scope.$eval(expression);\n                    angular.element($element)[0].scrollTop = scrollTop;\n                }\n            });\n        }\n    };\n})\n\n// Call a function when the element is scrolled\n// E.g. ac-on-scroll=\"listScrolled()\" \n// N.B. take care not to use the result to directly update an acScrollTo expression\n// as this will result in an infinite recursion!\n.directive('acOnScroll', function() {\n    return {\n        restrict: \"A\",\n        link: function(scope, element, attrs) {\n            var callbackName = attrs.acOnScroll;\n            if (callbackName.indexOf(\"()\") === callbackName.length - 2) {\n                callbackName = callbackName.substr(0, callbackName.length - 2);\n            }\n            var callback = scope[callbackName];\n            if (typeof callback === \"function\") {\n                element.bind(\"scroll\", function() {\n                    callback(element[0].scrollTop);\n                });\n            }\n        }\n    };\n})\n\n.factory('navKey', function() {\n    return {\n        'backspace': 8,\n        'tab': 9,\n        'enter': 13,\n        'escape': 27,\n        'pageUp': 33,\n        'pageDown': 34,\n        'end': 35,\n        'home': 36,\n        'leftArrow': 37,\n        'upArrow': 38,\n        'rightArrow': 39,\n        'downArrow': 40,\n        'del': 46\n    };\n})\n\n// safeApply service, courtesy Alex Vanston and Andrew Reutter\n.factory('safeApply', [function($rootScope) {\n    return function($scope, fn) {\n        var phase = $scope.$root.$$phase;\n        if (phase == '$apply' || phase == '$digest') {\n            if (fn) {\n                $scope.$eval(fn);\n            }\n        } else {\n            if (fn) {\n                $scope.$apply(fn);\n            } else {\n                $scope.$apply();\n            }\n        }\n    }\n}])\n\n// Service to allow host pages to change settings for all instances (in their module.run function)\n.factory('acuteSelectService', function() {\n\n    var defaultSettings = {\n        \"templatePath\": \"/acute.select/template\",\n        \"noItemsText\": \"No items found.\",\n        \"placeholderText\": \"Please select...\",\n        \"itemHeight\": 24,\n        \"itemsInView\": 10,\n        \"pageSize\": null,\n        \"minWidth\": \"100px\",\n        \"maxWidth\": \"\",\n        \"showSearchBox\": true,\n        \"comboMode\": false,\n        \"comboSelectOnFocus\": true,\n        \"loadOnCreate\": true,\n        \"loadOnOpen\": false,      // If true, while loadOnCreate is false, the load function will be called when the dropdown opens\n        \"allowCustomText\": false,\n        \"minSearchLength\": 0,\n        \"filterType\": \"contains\",    // or start/startsWith, end/endsWith\n        \"showFilterOptions\": false,\n        \"allowClear\": true,\n        \"debug\": false,\n        \"positionAbsolute\": false    // Is the select as a whole being positioned using \"position: absolute\"?\n    };\n\n    return {\n        getSettings: function() {\n            // Add trailing \"/\" to template path if not present\n            var len = defaultSettings.templatePath.length;\n            if (len > 0 && defaultSettings.templatePath.substr(len - 1, 1) !== \"/\") {\n                defaultSettings.templatePath += \"/\";\n            }\n            return angular.copy(defaultSettings);\n        },\n\n        updateSetting: function(settingName, value) {\n            updateSingleSetting(settingName, value);\n        },\n\n        updateSettings: function(settings) {\n            for (name in settings) {\n                updateSingleSetting(name, settings[name]);\n            }\n        }\n    };\n\n    function updateSingleSetting(settingName, value) {\n        if (defaultSettings.hasOwnProperty(settingName)) {\n            defaultSettings[settingName] = value;\n        }\n    }\n});"]}