{"version":3,"file":"dropdown.js","names":["_updateValidity","$ctrl","model","$setValidity","requiredfield","readonly","angular","equals","modelProperty","selectedItem","emptyValue","_isRequiredValid","_showDefaultItem","selectDefault","displayList","length","select","_findItemInList","item","list","entry","_rebuildDisplayList","srcListCopy","copy","filter","i","groupProperty","labelProperty","newList","headerobj","header","separator","showGroupHeader","push","_updateDisplayedItem","foundItem","$viewValue","modelIsEmptyValue","selectedIsEmptyValue","isPlaceholder","display","onInvalid","$event","value","app","component","require","bindings","placeholder","titleProperty","maxHeight","expandUp","searchText","searchTimeout","onSearch","onSelect","controller","$document","$timeout","$element","$scope","this","_initialised","_searchTimer","onModelChange","_documentClick","e","target","contains","off","$evalAsync","listVisible","ddOpen","searchBox","text","$onInit","element","addClass","$viewChangeListeners","$render","initialiseController","$postLink","$onChanges","changes","$onDestroy","opened","equal","var1","var2","searchChanged","cancel","noselectcallback","show","on","verticalPosition","$selectedRow","find","offsetParent","scrollTop","position","top","templateUrl","tios","util","cdnUrl"],"sources":["angular/component/dropdown.js"],"mappings":"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","sourcesContent":["//Based on basic principle from: https://www.codementor.io/angularjs/tutorial/create-dropdown-control\r\n//Usage: \r\n//set class=\"expandup\" to make expand upwards instead\r\n//labelProperty is optional, if not provided assumes object is a flat array of labels\r\n//modelproperty is optional. If not provided, will check equivalence of model against list entries via properties.\r\n//If provided, uses modelproperty of list items and returns that property as the model value\r\n//max-height is optional and is applied as-is in the style=\"max-height:xx;\" attribute\r\n//headerProperty will create fake entries with the headerProperty value on first entry and those entries\r\n//where the previous entry's headerProperty is different. Must be used in conjunction with labelProperty\r\n//searchbox enables entering of text, but you still have to click an entry\r\n//onsearch is the callback that returns the searched text.\r\n//selectdefault = if only one item, automatically select it\r\n//required - if required, sets the hidden field's value to 1 or null depending on whether the selected Item's value matches emptyValue or not, using ng-required internally\r\n\r\n//\r\n\r\n(function () {\r\n 'use strict';\r\n // Generic methods common to all instances of this component\r\n\r\n //Validation based on: http://plnkr.co/edit/octwC4BCuXLmRhHgLD8T?p=preview\r\n function _isRequiredValid($ctrl) {\r\n //If the required attribute is set on the directive, and it's not read only, make the field required if the value is empty\r\n if ($ctrl.requiredfield && !$ctrl.readonly) {\r\n //If this entry is empty, required field should be true (as long as the required attribute is set)\r\n //console.log('$ctrl.selectedItem', $ctrl.selectedItem)\r\n\r\n return !angular.equals((!!$ctrl.modelProperty && !!$ctrl.selectedItem ? $ctrl.selectedItem[$ctrl.modelProperty] : $ctrl.selectedItem), $ctrl.emptyValue);\r\n }\r\n //If directive is not a required field, return that the required form value is not required\r\n return true;\r\n }\r\n\r\n function _updateValidity($ctrl) {\r\n //Set the required status (as reported to the containing form) based on whether a valid value has been selected\r\n $ctrl.model.$setValidity(\"\", _isRequiredValid($ctrl));\r\n //SetValidity key string \"required\" removed to set base validity.\r\n }\r\n\r\n function _showDefaultItem($ctrl) {\r\n if ($ctrl.selectDefault && $ctrl.displayList.length == 1) {\r\n $ctrl.select($ctrl.displayList[0], true);//select item, ignoring callback.\r\n }\r\n }\r\n\r\n function _findItemInList($ctrl, item) {\r\n if ($ctrl.list && $ctrl.list.length) {\r\n for (var entry of $ctrl.list) {\r\n if (!$ctrl.modelProperty) {\r\n if (angular.equals(item, entry)) {\r\n return entry;\r\n }\r\n } else {\r\n if (angular.equals(item, entry[$ctrl.modelProperty])) {\r\n return entry;\r\n }\r\n }\r\n }\r\n }\r\n //This will have returned if found, otherwise return null\r\n return null;\r\n }\r\n\r\n\r\n\r\n function _rebuildDisplayList($ctrl) {\r\n // Filter the source list to not include items that are in the emptyValue (if provided)\r\n var srcListCopy = !!$ctrl.list ? angular.copy($ctrl.list.filter(function (i) {\r\n return $ctrl.emptyValue == null || !angular.equals((!!$ctrl.modelProperty ? i[$ctrl.modelProperty] : i), $ctrl.emptyValue);\r\n }) || []) : [];\r\n\r\n if (srcListCopy.length && $ctrl.groupProperty && $ctrl.labelProperty) {\r\n var newList = [];\r\n for (var i = 0; i < srcListCopy.length; i++) {\r\n\r\n if (i === 0 || srcListCopy[i - 1][$ctrl.groupProperty] !== srcListCopy[i][$ctrl.groupProperty]) { //first row or different to previous group\r\n var headerobj = { readonly: true, header: true, separator: !$ctrl.showGroupHeader };\r\n headerobj[$ctrl.labelProperty] = srcListCopy[i][$ctrl.groupProperty];\r\n newList.push(headerobj);\r\n }\r\n newList.push(srcListCopy[i]);\r\n }\r\n return newList;\r\n } else {\r\n return srcListCopy;\r\n }\r\n\r\n }\r\n\r\n function _updateDisplayedItem($ctrl) {\r\n var foundItem = _findItemInList($ctrl, $ctrl.model.$viewValue);\r\n if (foundItem === null) {\r\n $ctrl.selectedItem = angular.copy($ctrl.emptyValue);\r\n } else {\r\n $ctrl.selectedItem = foundItem;\r\n }\r\n\r\n var modelIsEmptyValue = angular.equals($ctrl.model.$viewValue, $ctrl.emptyValue);\r\n var selectedIsEmptyValue = angular.equals($ctrl.selectedItem, $ctrl.emptyValue);\r\n\r\n $ctrl.isPlaceholder = (modelIsEmptyValue || selectedIsEmptyValue || (!!$ctrl.labelProperty && typeof ($ctrl.selectedItem[$ctrl.labelProperty]) === 'undefined'));\r\n\r\n _updateValidity($ctrl);\r\n\r\n if (!$ctrl.isPlaceholder) {\r\n if ($ctrl.labelProperty && !selectedIsEmptyValue) {\r\n $ctrl.display = $ctrl.selectedItem[$ctrl.labelProperty];\r\n } else {\r\n $ctrl.display = $ctrl.selectedItem;\r\n }\r\n }\r\n\r\n // If the value in the model is not found (and has legitimately been passed and is not the empty value), trigger the invalid callback\r\n if (foundItem === null && !modelIsEmptyValue && (typeof $ctrl.model.$viewValue !== 'undefined' && $ctrl.model.$viewValue !== null)) {\r\n //console.log('foundItem', foundItem);\r\n //console.log('modelIsEmptyValue', modelIsEmptyValue);\r\n //console.log('selectedIsEmptyValue', selectedIsEmptyValue);\r\n //console.log('Empty', $ctrl.emptyValue);\r\n //console.log('viewvalue', $ctrl.model.$viewValue);\r\n //console.log('selectedItem', $ctrl.selectedItem);\r\n $ctrl.onInvalid({ $event: { value: $ctrl.model.$viewValue } });\r\n }\r\n }\r\n\r\n var dropdownController = function ($document, $timeout, $element, $scope) {\r\n var $ctrl = this;\r\n\r\n //Internal variables\r\n var _initialised = false;\r\n var _searchTimer = null;\r\n\r\n //Init function\r\n $ctrl.$onInit = $onInit;\r\n $ctrl.$postLink = $postLink;\r\n $ctrl.$onChanges = $onChanges;\r\n $ctrl.$onDestroy = $onDestroy;\r\n\r\n //Set defaults\r\n\r\n //Frontend variables\r\n $ctrl.opened = false;//Has the dropdown been opened? Sets on first open.\r\n\r\n $ctrl.ddOpen = false;\r\n $ctrl.display = null;//holds shown value\r\n $ctrl.listVisible = false;\r\n $ctrl.displayList = [];\r\n //TODO try the below line\r\n //$ctrl.displayList = _rebuildDisplayList($ctrl);\r\n\r\n $ctrl.searchBox = typeof $ctrl.onSearch !== 'undefined';//Set to searchable if either the model or the search callback is set on load\r\n $ctrl.searchText = ''; //Text entered in search field\r\n //TODO!\r\n $ctrl.isPlaceholder = true;\r\n\r\n $ctrl.selectedItem = null; //placeholder for selected entry in list\r\n\r\n // #region functionality\r\n\r\n\r\n\r\n\r\n $ctrl.equal = function (var1, var2) {\r\n return angular.equals(var1, var2);\r\n };\r\n\r\n $ctrl.searchChanged = function () {\r\n $ctrl.selectedItem = $ctrl.emptyValue;//clear selection\r\n\r\n if ($ctrl.searchTimeout > 0) {\r\n // Do not fire search method immediately on change.\r\n // prevent instant triggering by using a rolling timeout\r\n if (_searchTimer) $timeout.cancel(_searchTimer);\r\n _searchTimer = $timeout(function () {\r\n $ctrl.onSearch({ $event: { text: $ctrl.searchText } });//return searched text to controller\r\n }, $ctrl.searchTimeout);//end timeout\r\n } else {\r\n $ctrl.onSearch({ $event: { text: $ctrl.searchText } });//return searched text to controller\r\n }\r\n };\r\n\r\n $ctrl.select = function (item, noselectcallback) {\r\n if (!$ctrl.readonly) {\r\n $ctrl.listVisible = false;\r\n $ctrl.ddOpen = false;\r\n $document.off('click', _documentClick);//unbind the click-away event\r\n\r\n if (item && !item.readonly && !angular.equals(item, $ctrl.emptyValue)) {\r\n //console.log('first clause', item, typeof item);\r\n $scope.$evalAsync(function () {\r\n $ctrl.selectedItem = item;\r\n\r\n //$ctrl.isPlaceholder = false;\r\n //DO not update the model - the parent controller should do this, which will trigger validation\r\n //_updateValidity($ctrl);\r\n //$ctrl.model.$setViewValue(viewValue);//on selection set model to either the property or list item\r\n\r\n //No longer update the search box text - that should be done by the controller based on the properties of the selected object.\r\n //if ($ctrl.searchBox) {\r\n //set textbox content if using searchbox - must be labelProperty or text if it doesn't have that\r\n //$ctrl.searchText = angular.copy(($ctrl.labelProperty ? item[$ctrl.labelProperty]: item));\r\n //}\r\n\r\n if (!noselectcallback) {\r\n $ctrl.onSelect({ $event: { item: item } }); //Return the item as the viewValue (be that the item itself or its model property)\r\n //$ctrl.onSelect(item, $element);\r\n }\r\n });\r\n } else if (angular.equals(item, $ctrl.emptyValue) || item === null) {\r\n //console.log('second clause', item, typeof item);\r\n $scope.$evalAsync(function () {\r\n //$ctrl.isPlaceholder = true;\r\n $ctrl.selectedItem = $ctrl.emptyValue;\r\n //DO not update the model - the parent controller should do this, which will trigger validation\r\n //_updateValidity($ctrl);\r\n //$ctrl.model.$setViewValue($ctrl.emptyValue);\r\n if (!noselectcallback) {\r\n $ctrl.onSelect({ $event: { item: $ctrl.emptyValue } });\r\n //$ctrl.onSelect(null, $element);\r\n }\r\n });\r\n }\r\n }\r\n\r\n _updateDisplayedItem($ctrl);\r\n };\r\n\r\n $ctrl.show = function () {\r\n if (!$ctrl.readonly) {\r\n $ctrl.opened = true;\r\n $ctrl.listVisible = !$ctrl.listVisible || $ctrl.searchBox;\r\n if ($ctrl.listVisible) {\r\n $document.on('click', _documentClick);//bind the click-away event\r\n\r\n if (typeof (jQuery) !== 'undefined') {\r\n $timeout(function () {\r\n //Find vertical position of selected row\r\n var verticalPosition = 0;\r\n var $selectedRow = $element.find('.dropdown-list .selected');\r\n if ($selectedRow.length) {\r\n verticalPosition = $selectedRow.offsetParent().scrollTop() + $selectedRow.position().top;// - ($selectedRow.offsetParent().height() / 2);//halfway up scroller\r\n }\r\n $element.find('.dropdown-list').scrollTop(verticalPosition);//scroll to selected entry\r\n });\r\n\r\n //This delay must match the transition duration of the list opening in order to hide scrollbar whilst transitioning.\r\n $timeout(function () { $ctrl.ddOpen = true; }, 400);\r\n }\r\n } else {\r\n $ctrl.ddOpen = false;\r\n $document.off('click', _documentClick);//unbind the click-away event\r\n }\r\n }\r\n };\r\n\r\n function onModelChange() {\r\n _updateDisplayedItem($ctrl);\r\n }\r\n\r\n function _documentClick(e) {\r\n if ($element !== e.target && !$element[0].contains(e.target)) {\r\n //click away from element\r\n $document.off('click', _documentClick);//cancel the click-away when clicking off\r\n\r\n // Using evalasync to trigger refresh\r\n $scope.$evalAsync(function () {\r\n $ctrl.listVisible = false;\r\n $ctrl.ddOpen = false;\r\n if ($ctrl.searchBox) {//if searchbox, clear text when nothing has been picked\r\n if (!angular.equals($ctrl.selectedItem, $ctrl.emptyValue)) {\r\n $ctrl.searchText = '';\r\n $ctrl.onSearch({ $event: { text: $ctrl.searchText } });//return searched text to controller\r\n }\r\n }\r\n });\r\n } else {\r\n //clicked on element, do nothing as show and select methods do this\r\n }\r\n }\r\n\r\n // #endregion\r\n\r\n function $onInit() {\r\n //set up defaults\r\n initialiseController();\r\n }\r\n\r\n function $postLink() {\r\n }\r\n\r\n function $onChanges(changes) {\r\n if (_initialised) {\r\n if (changes.list) {\r\n $ctrl.displayList = _rebuildDisplayList($ctrl);\r\n if (!$ctrl.searchBox) {\r\n _showDefaultItem($ctrl);\r\n //if list has changed, check to see whether selection is present - if not, reset it to emptyValue.\r\n var foundItem = _findItemInList($ctrl, $ctrl.model.$viewValue)\r\n\r\n $ctrl.select((foundItem !== null ? foundItem : $ctrl.emptyValue), true);//select in list but do not trigger event (when not searching)\r\n _updateValidity($ctrl);\r\n }\r\n }\r\n\r\n if (changes.searchText) {\r\n //console.log('searchText', $ctrl.searchText);\r\n if ($ctrl.searchBox) {\r\n // Clear the selected item when searching\r\n $ctrl.selectedItem = angular.copy($ctrl.emptyValue);\r\n }\r\n }\r\n\r\n //Update the validity state if the required attribute changes\r\n if (changes.requiredfield) {\r\n _updateValidity($ctrl);\r\n }\r\n }\r\n }\r\n\r\n function $onDestroy() {\r\n $document.off('click', _documentClick);\r\n }\r\n\r\n function initialiseController() {\r\n //Handle parameters passed from the bindings\r\n\r\n if ($ctrl.expandUp) {\r\n angular.element($element).addClass('expandup');\r\n }\r\n\r\n $ctrl.requiredfield = !!$ctrl.requiredfield;//Coerce to false if undefined\r\n\r\n $ctrl.emptyValue = $ctrl.emptyValue || null;//emptyvalue defaults to null\r\n\r\n $ctrl.selectedItem = angular.copy($ctrl.emptyValue);\r\n\r\n // We need to bind to the model change events for this to work\r\n $ctrl.model.$viewChangeListeners.push(onModelChange);\r\n $ctrl.model.$render = onModelChange;\r\n\r\n if (!$ctrl.searchTimeout) $ctrl.searchTimeout = 0;\r\n if (typeof $ctrl.showGroupHeader === 'undefined') $ctrl.showGroupHeader = true;\r\n // Because default function wrappers are set after initial binding, our $ctrl.searchBox won't be affected by this.\r\n if (typeof $ctrl.onSearch !== 'function') $ctrl.onSearch = function () { };\r\n if (typeof $ctrl.onSelect !== 'function') $ctrl.onSelect = function () { };\r\n if (typeof $ctrl.onInvalid !== 'function') $ctrl.onInvalid = function () { };\r\n\r\n $ctrl.displayList = _rebuildDisplayList($ctrl);\r\n\r\n _showDefaultItem($ctrl);\r\n _updateValidity($ctrl);\r\n\r\n //console.log('dropdown', $ctrl.labelProperty, $ctrl.modelProperty, $ctrl.titleProperty);\r\n\r\n //Mark the controller as having been initialised, so that changes can start monitoring (prevents double-triggering)\r\n _initialised = true;\r\n }\r\n };\r\n\r\n app.component('dropdown', {\r\n require: {\r\n model: 'ngModel' // get the model directly from the ng-model declaration\r\n },\r\n bindings: {\r\n placeholder: '@',// Placeholder string for unselected appearance\r\n list: '<', // Values with which to populate the dropdown\r\n labelProperty: \"@?\",//property of list object to display as text\r\n modelProperty: \"@?\",//property of selection to return as model (optional)\r\n titleProperty: \"@?\",//property of selection to return as model (optional)\r\n groupProperty: \"@?\",//property of list to use as grouping header\r\n showGroupHeader: \"