').append(clone);
-
- var transcludedMatch = transcluded.querySelectorAll('.ui-select-match');
- transcludedMatch.removeAttr('ui-select-match'); //To avoid loop in case directive as attr
- transcludedMatch.removeAttr('data-ui-select-match'); // Properly handle HTML5 data-attributes
- if (transcludedMatch.length !== 1) {
- throw uiSelectMinErr('transcluded', "Expected 1 .ui-select-match but got '{0}'.", transcludedMatch.length);
- }
- element.querySelectorAll('.ui-select-match').replaceWith(transcludedMatch);
-
- var transcludedChoices = transcluded.querySelectorAll('.ui-select-choices');
- transcludedChoices.removeAttr('ui-select-choices'); //To avoid loop in case directive as attr
- transcludedChoices.removeAttr('data-ui-select-choices'); // Properly handle HTML5 data-attributes
- if (transcludedChoices.length !== 1) {
- throw uiSelectMinErr('transcluded', "Expected 1 .ui-select-choices but got '{0}'.", transcludedChoices.length);
- }
- element.querySelectorAll('.ui-select-choices').replaceWith(transcludedChoices);
-
- var transcludedNoChoice = transcluded.querySelectorAll('.ui-select-no-choice');
- transcludedNoChoice.removeAttr('ui-select-no-choice'); //To avoid loop in case directive as attr
- transcludedNoChoice.removeAttr('data-ui-select-no-choice'); // Properly handle HTML5 data-attributes
- if (transcludedNoChoice.length == 1) {
- element.querySelectorAll('.ui-select-no-choice').replaceWith(transcludedNoChoice);
- }
- });
-
- // Support for appending the select field to the body when its open
- var appendToBody = scope.$eval(attrs.appendToBody);
- if (appendToBody !== undefined ? appendToBody : uiSelectConfig.appendToBody) {
- scope.$watch('$select.open', function(isOpen) {
- if (isOpen) {
- positionDropdown();
- } else {
- resetDropdown();
- }
- });
-
- // Move the dropdown back to its original location when the scope is destroyed. Otherwise
- // it might stick around when the user routes away or the select field is otherwise removed
- scope.$on('$destroy', function() {
- resetDropdown();
- });
- }
-
- // Hold on to a reference to the .ui-select-container element for appendToBody support
- var placeholder = null,
- originalWidth = '';
-
- function positionDropdown() {
- // Remember the absolute position of the element
- var offset = uisOffset(element);
-
- // Clone the element into a placeholder element to take its original place in the DOM
- placeholder = angular.element('
');
- placeholder[0].style.width = offset.width + 'px';
- placeholder[0].style.height = offset.height + 'px';
- element.after(placeholder);
-
- // Remember the original value of the element width inline style, so it can be restored
- // when the dropdown is closed
- originalWidth = element[0].style.width;
-
- // Now move the actual dropdown element to the end of the body
- $document.find('body').append(element);
-
- element[0].style.position = 'absolute';
- element[0].style.left = offset.left + 'px';
- element[0].style.top = offset.top + 'px';
- element[0].style.width = offset.width + 'px';
- }
-
- function resetDropdown() {
- if (placeholder === null) {
- // The dropdown has not actually been display yet, so there's nothing to reset
- return;
- }
-
- // Move the dropdown element back to its original location in the DOM
- placeholder.replaceWith(element);
- placeholder = null;
-
- element[0].style.position = '';
- element[0].style.left = '';
- element[0].style.top = '';
- element[0].style.width = originalWidth;
-
- // Set focus back on to the moved element
- $select.setFocus();
- }
-
- // Hold on to a reference to the .ui-select-dropdown element for direction support.
- var dropdown = null,
- directionUpClassName = 'direction-up';
-
- // Support changing the direction of the dropdown if there isn't enough space to render it.
- scope.$watch('$select.open', function() {
-
- if ($select.dropdownPosition === 'auto' || $select.dropdownPosition === 'up'){
- scope.calculateDropdownPos();
- }
-
- });
-
- var setDropdownPosUp = function(offset, offsetDropdown){
-
- offset = offset || uisOffset(element);
- offsetDropdown = offsetDropdown || uisOffset(dropdown);
-
- dropdown[0].style.position = 'absolute';
- dropdown[0].style.top = (offsetDropdown.height * -1) + 'px';
- element.addClass(directionUpClassName);
-
- };
-
- var setDropdownPosDown = function(offset, offsetDropdown){
-
- element.removeClass(directionUpClassName);
-
- offset = offset || uisOffset(element);
- offsetDropdown = offsetDropdown || uisOffset(dropdown);
-
- dropdown[0].style.position = '';
- dropdown[0].style.top = '';
-
- };
-
- var calculateDropdownPosAfterAnimation = function() {
- // Delay positioning the dropdown until all choices have been added so its height is correct.
- $timeout(function() {
- if ($select.dropdownPosition === 'up') {
- //Go UP
- setDropdownPosUp();
- } else {
- //AUTO
- element.removeClass(directionUpClassName);
-
- var offset = uisOffset(element);
- var offsetDropdown = uisOffset(dropdown);
-
- //https://code.google.com/p/chromium/issues/detail?id=342307#c4
- var scrollTop = $document[0].documentElement.scrollTop || $document[0].body.scrollTop; //To make it cross browser (blink, webkit, IE, Firefox).
-
- // Determine if the direction of the dropdown needs to be changed.
- if (offset.top + offset.height + offsetDropdown.height > scrollTop + $document[0].documentElement.clientHeight) {
- //Go UP
- setDropdownPosUp(offset, offsetDropdown);
- }else{
- //Go DOWN
- setDropdownPosDown(offset, offsetDropdown);
- }
- }
-
- // Display the dropdown once it has been positioned.
- dropdown[0].style.opacity = 1;
- });
- };
-
- var opened = false;
-
- scope.calculateDropdownPos = function() {
- if ($select.open) {
- dropdown = angular.element(element).querySelectorAll('.ui-select-dropdown');
-
- if (dropdown.length === 0) {
- return;
- }
-
- // Hide the dropdown so there is no flicker until $timeout is done executing.
- if ($select.search === '' && !opened) {
- dropdown[0].style.opacity = 0;
- opened = true;
- }
-
- if (!uisOffset(dropdown).height && $select.$animate && $select.$animate.on && $select.$animate.enabled(dropdown)) {
- var needsCalculated = true;
-
- $select.$animate.on('enter', dropdown, function (elem, phase) {
- if (phase === 'close' && needsCalculated) {
- calculateDropdownPosAfterAnimation();
- needsCalculated = false;
- }
- });
- } else {
- calculateDropdownPosAfterAnimation();
- }
- } else {
- if (dropdown === null || dropdown.length === 0) {
- return;
- }
-
- // Reset the position of the dropdown.
- dropdown[0].style.opacity = 0;
- dropdown[0].style.position = '';
- dropdown[0].style.top = '';
- element.removeClass(directionUpClassName);
- }
- };
- };
- }
- };
-}]);
-
-uis.directive('uiSelectMatch', ['uiSelectConfig', function(uiSelectConfig) {
- return {
- restrict: 'EA',
- require: '^uiSelect',
- replace: true,
- transclude: true,
- templateUrl: function(tElement) {
- // Needed so the uiSelect can detect the transcluded content
- tElement.addClass('ui-select-match');
-
- var parent = tElement.parent();
- // Gets theme attribute from parent (ui-select)
- var theme = getAttribute(parent, 'theme') || uiSelectConfig.theme;
- var multi = angular.isDefined(getAttribute(parent, 'multiple'));
-
- return theme + (multi ? '/match-multiple.tpl.html' : '/match.tpl.html');
- },
- link: function(scope, element, attrs, $select) {
- $select.lockChoiceExpression = attrs.uiLockChoice;
- attrs.$observe('placeholder', function(placeholder) {
- $select.placeholder = placeholder !== undefined ? placeholder : uiSelectConfig.placeholder;
- });
-
- function setAllowClear(allow) {
- $select.allowClear = (angular.isDefined(allow)) ? (allow === '') ? true : (allow.toLowerCase() === 'true') : false;
- }
-
- attrs.$observe('allowClear', setAllowClear);
- setAllowClear(attrs.allowClear);
-
- if($select.multiple){
- $select.sizeSearchInput();
- }
-
- }
- };
-
- function getAttribute(elem, attribute) {
- if (elem[0].hasAttribute(attribute))
- return elem.attr(attribute);
-
- if (elem[0].hasAttribute('data-' + attribute))
- return elem.attr('data-' + attribute);
-
- if (elem[0].hasAttribute('x-' + attribute))
- return elem.attr('x-' + attribute);
- }
-}]);
-
-uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelectMinErr, $timeout) {
- return {
- restrict: 'EA',
- require: ['^uiSelect', '^ngModel'],
-
- controller: ['$scope','$timeout', function($scope, $timeout){
-
- var ctrl = this,
- $select = $scope.$select,
- ngModel;
-
- if (angular.isUndefined($select.selected))
- $select.selected = [];
-
- //Wait for link fn to inject it
- $scope.$evalAsync(function(){ ngModel = $scope.ngModel; });
-
- ctrl.activeMatchIndex = -1;
-
- ctrl.updateModel = function(){
- ngModel.$setViewValue(Date.now()); //Set timestamp as a unique string to force changes
- ctrl.refreshComponent();
- };
-
- ctrl.refreshComponent = function(){
- //Remove already selected items
- //e.g. When user clicks on a selection, the selected array changes and
- //the dropdown should remove that item
- if($select.refreshItems){
- $select.refreshItems();
- }
- if($select.sizeSearchInput){
- $select.sizeSearchInput();
- }
- };
-
- // Remove item from multiple select
- ctrl.removeChoice = function(index){
-
- // if the choice is locked, don't remove it
- if($select.isLocked(null, index)) return false;
-
- var removedChoice = $select.selected[index];
-
- var locals = {};
- locals[$select.parserResult.itemName] = removedChoice;
-
- $select.selected.splice(index, 1);
- ctrl.activeMatchIndex = -1;
- $select.sizeSearchInput();
-
- // Give some time for scope propagation.
- $timeout(function(){
- $select.onRemoveCallback($scope, {
- $item: removedChoice,
- $model: $select.parserResult.modelMapper($scope, locals)
- });
- });
-
- ctrl.updateModel();
-
- return true;
- };
-
- ctrl.getPlaceholder = function(){
- //Refactor single?
- if($select.selected && $select.selected.length) return;
- return $select.placeholder;
- };
-
-
- }],
- controllerAs: '$selectMultiple',
-
- link: function(scope, element, attrs, ctrls) {
-
- var $select = ctrls[0];
- var ngModel = scope.ngModel = ctrls[1];
- var $selectMultiple = scope.$selectMultiple;
-
- //$select.selected = raw selected objects (ignoring any property binding)
-
- $select.multiple = true;
-
- //Input that will handle focus
- $select.focusInput = $select.searchInput;
-
- //Properly check for empty if set to multiple
- ngModel.$isEmpty = function(value) {
- return !value || value.length === 0;
- };
-
- //From view --> model
- ngModel.$parsers.unshift(function () {
- var locals = {},
- result,
- resultMultiple = [];
- for (var j = $select.selected.length - 1; j >= 0; j--) {
- locals = {};
- locals[$select.parserResult.itemName] = $select.selected[j];
- result = $select.parserResult.modelMapper(scope, locals);
- resultMultiple.unshift(result);
- }
- return resultMultiple;
- });
-
- // From model --> view
- ngModel.$formatters.unshift(function (inputValue) {
- var data = $select.parserResult && $select.parserResult.source (scope, { $select : {search:''}}), //Overwrite $search
- locals = {},
- result;
- if (!data) return inputValue;
- var resultMultiple = [];
- var checkFnMultiple = function(list, value){
- if (!list || !list.length) return;
- for (var p = list.length - 1; p >= 0; p--) {
- locals[$select.parserResult.itemName] = list[p];
- result = $select.parserResult.modelMapper(scope, locals);
- if($select.parserResult.trackByExp){
- var propsItemNameMatches = /(\w*)\./.exec($select.parserResult.trackByExp);
- var matches = /\.([^\s]+)/.exec($select.parserResult.trackByExp);
- if(propsItemNameMatches && propsItemNameMatches.length > 0 && propsItemNameMatches[1] == $select.parserResult.itemName){
- if(matches && matches.length>0 && result[matches[1]] == value[matches[1]]){
- resultMultiple.unshift(list[p]);
- return true;
- }
- }
- }
- if (angular.equals(result,value)){
- resultMultiple.unshift(list[p]);
- return true;
- }
- }
- return false;
- };
- if (!inputValue) return resultMultiple; //If ngModel was undefined
- for (var k = inputValue.length - 1; k >= 0; k--) {
- //Check model array of currently selected items
- if (!checkFnMultiple($select.selected, inputValue[k])){
- //Check model array of all items available
- if (!checkFnMultiple(data, inputValue[k])){
- //If not found on previous lists, just add it directly to resultMultiple
- resultMultiple.unshift(inputValue[k]);
- }
- }
- }
- return resultMultiple;
- });
-
- //Watch for external model changes
- scope.$watchCollection(function(){ return ngModel.$modelValue; }, function(newValue, oldValue) {
- if (oldValue != newValue){
- //update the view value with fresh data from items, if there is a valid model value
- if(angular.isDefined(ngModel.$modelValue)) {
- ngModel.$modelValue = null; //Force scope model value and ngModel value to be out of sync to re-run formatters
- }
- $selectMultiple.refreshComponent();
- }
- });
-
- ngModel.$render = function() {
- // Make sure that model value is array
- if(!angular.isArray(ngModel.$viewValue)){
- // Have tolerance for null or undefined values
- if(angular.isUndefined(ngModel.$viewValue) || ngModel.$viewValue === null){
- ngModel.$viewValue = [];
- } else {
- throw uiSelectMinErr('multiarr', "Expected model value to be array but got '{0}'", ngModel.$viewValue);
- }
- }
- $select.selected = ngModel.$viewValue;
- $selectMultiple.refreshComponent();
- scope.$evalAsync(); //To force $digest
- };
-
- scope.$on('uis:select', function (event, item) {
- if($select.selected.length >= $select.limit) {
- return;
- }
- $select.selected.push(item);
- $selectMultiple.updateModel();
- });
-
- scope.$on('uis:activate', function () {
- $selectMultiple.activeMatchIndex = -1;
- });
-
- scope.$watch('$select.disabled', function(newValue, oldValue) {
- // As the search input field may now become visible, it may be necessary to recompute its size
- if (oldValue && !newValue) $select.sizeSearchInput();
- });
-
- $select.searchInput.on('keydown', function(e) {
- var key = e.which;
- scope.$apply(function() {
- var processed = false;
- // var tagged = false; //Checkme
- if(KEY.isHorizontalMovement(key)){
- processed = _handleMatchSelection(key);
- }
- if (processed && key != KEY.TAB) {
- //TODO Check si el tab selecciona aun correctamente
- //Crear test
- e.preventDefault();
- e.stopPropagation();
- }
- });
- });
- function _getCaretPosition(el) {
- if(angular.isNumber(el.selectionStart)) return el.selectionStart;
- // selectionStart is not supported in IE8 and we don't want hacky workarounds so we compromise
- else return el.value.length;
- }
- // Handles selected options in "multiple" mode
- function _handleMatchSelection(key){
- var caretPosition = _getCaretPosition($select.searchInput[0]),
- length = $select.selected.length,
- // none = -1,
- first = 0,
- last = length-1,
- curr = $selectMultiple.activeMatchIndex,
- next = $selectMultiple.activeMatchIndex+1,
- prev = $selectMultiple.activeMatchIndex-1,
- newIndex = curr;
-
- if(caretPosition > 0 || ($select.search.length && key == KEY.RIGHT)) return false;
-
- $select.close();
-
- function getNewActiveMatchIndex(){
- switch(key){
- case KEY.LEFT:
- // Select previous/first item
- if(~$selectMultiple.activeMatchIndex) return prev;
- // Select last item
- else return last;
- break;
- case KEY.RIGHT:
- // Open drop-down
- if(!~$selectMultiple.activeMatchIndex || curr === last){
- $select.activate();
- return false;
- }
- // Select next/last item
- else return next;
- break;
- case KEY.BACKSPACE:
- // Remove selected item and select previous/first
- if(~$selectMultiple.activeMatchIndex){
- if($selectMultiple.removeChoice(curr)) {
- return prev;
- } else {
- return curr;
- }
-
- } else {
- // If nothing yet selected, select last item
- return last;
- }
- break;
- case KEY.DELETE:
- // Remove selected item and select next item
- if(~$selectMultiple.activeMatchIndex){
- $selectMultiple.removeChoice($selectMultiple.activeMatchIndex);
- return curr;
- }
- else return false;
- }
- }
-
- newIndex = getNewActiveMatchIndex();
-
- if(!$select.selected.length || newIndex === false) $selectMultiple.activeMatchIndex = -1;
- else $selectMultiple.activeMatchIndex = Math.min(last,Math.max(first,newIndex));
-
- return true;
- }
-
- $select.searchInput.on('keyup', function(e) {
-
- if ( ! KEY.isVerticalMovement(e.which) ) {
- scope.$evalAsync( function () {
- $select.activeIndex = $select.taggingLabel === false ? -1 : 0;
- });
- }
- // Push a "create new" item into array if there is a search string
- if ( $select.tagging.isActivated && $select.search.length > 0 ) {
-
- // return early with these keys
- if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC || KEY.isVerticalMovement(e.which) ) {
- return;
- }
- // always reset the activeIndex to the first item when tagging
- $select.activeIndex = $select.taggingLabel === false ? -1 : 0;
- // taggingLabel === false bypasses all of this
- if ($select.taggingLabel === false) return;
-
- var items = angular.copy( $select.items );
- var stashArr = angular.copy( $select.items );
- var newItem;
- var item;
- var hasTag = false;
- var dupeIndex = -1;
- var tagItems;
- var tagItem;
-
- // case for object tagging via transform `$select.tagging.fct` function
- if ( $select.tagging.fct !== undefined) {
- tagItems = $select.$filter('filter')(items,{'isTag': true});
- if ( tagItems.length > 0 ) {
- tagItem = tagItems[0];
- }
- // remove the first element, if it has the `isTag` prop we generate a new one with each keyup, shaving the previous
- if ( items.length > 0 && tagItem ) {
- hasTag = true;
- items = items.slice(1,items.length);
- stashArr = stashArr.slice(1,stashArr.length);
- }
- newItem = $select.tagging.fct($select.search);
- // verify the new tag doesn't match the value of a possible selection choice or an already selected item.
- if (
- stashArr.some(function (origItem) {
- return angular.equals(origItem, newItem);
- }) ||
- $select.selected.some(function (origItem) {
- return angular.equals(origItem, newItem);
- })
- ) {
- scope.$evalAsync(function () {
- $select.activeIndex = 0;
- $select.items = items;
- });
- return;
- }
- if (newItem) newItem.isTag = true;
- // handle newItem string and stripping dupes in tagging string context
- } else {
- // find any tagging items already in the $select.items array and store them
- tagItems = $select.$filter('filter')(items,function (item) {
- return item.match($select.taggingLabel);
- });
- if ( tagItems.length > 0 ) {
- tagItem = tagItems[0];
- }
- item = items[0];
- // remove existing tag item if found (should only ever be one tag item)
- if ( item !== undefined && items.length > 0 && tagItem ) {
- hasTag = true;
- items = items.slice(1,items.length);
- stashArr = stashArr.slice(1,stashArr.length);
- }
- newItem = $select.search+' '+$select.taggingLabel;
- if ( _findApproxDupe($select.selected, $select.search) > -1 ) {
- return;
- }
- // verify the the tag doesn't match the value of an existing item from
- // the searched data set or the items already selected
- if ( _findCaseInsensitiveDupe(stashArr.concat($select.selected)) ) {
- // if there is a tag from prev iteration, strip it / queue the change
- // and return early
- if ( hasTag ) {
- items = stashArr;
- scope.$evalAsync( function () {
- $select.activeIndex = 0;
- $select.items = items;
- });
- }
- return;
- }
- if ( _findCaseInsensitiveDupe(stashArr) ) {
- // if there is a tag from prev iteration, strip it
- if ( hasTag ) {
- $select.items = stashArr.slice(1,stashArr.length);
- }
- return;
- }
- }
- if ( hasTag ) dupeIndex = _findApproxDupe($select.selected, newItem);
- // dupe found, shave the first item
- if ( dupeIndex > -1 ) {
- items = items.slice(dupeIndex+1,items.length-1);
- } else {
- items = [];
- if (newItem) items.push(newItem);
- items = items.concat(stashArr);
- }
- scope.$evalAsync( function () {
- $select.activeIndex = 0;
- $select.items = items;
-
- if ($select.isGrouped) {
- // update item references in groups, so that indexOf will work after angular.copy
- var itemsWithoutTag = newItem ? items.slice(1) : items;
- $select.setItemsFn(itemsWithoutTag);
- if (newItem) {
- // add tag item as a new group
- $select.items.unshift(newItem);
- $select.groups.unshift({name: '', items: [newItem], tagging: true});
- }
- }
- });
- }
- });
- function _findCaseInsensitiveDupe(arr) {
- if ( arr === undefined || $select.search === undefined ) {
- return false;
- }
- var hasDupe = arr.filter( function (origItem) {
- if ( $select.search.toUpperCase() === undefined || origItem === undefined ) {
- return false;
- }
- return origItem.toUpperCase() === $select.search.toUpperCase();
- }).length > 0;
-
- return hasDupe;
- }
- function _findApproxDupe(haystack, needle) {
- var dupeIndex = -1;
- if(angular.isArray(haystack)) {
- var tempArr = angular.copy(haystack);
- for (var i = 0; i
model
- ngModel.$parsers.unshift(function (inputValue) {
- var locals = {},
- result;
- locals[$select.parserResult.itemName] = inputValue;
- result = $select.parserResult.modelMapper(scope, locals);
- return result;
- });
-
- //From model --> view
- ngModel.$formatters.unshift(function (inputValue) {
- var data = $select.parserResult && $select.parserResult.source (scope, { $select : {search:''}}), //Overwrite $search
- locals = {},
- result;
- if (data){
- var checkFnSingle = function(d){
- locals[$select.parserResult.itemName] = d;
- result = $select.parserResult.modelMapper(scope, locals);
- return result === inputValue;
- };
- //If possible pass same object stored in $select.selected
- if ($select.selected && checkFnSingle($select.selected)) {
- return $select.selected;
- }
- for (var i = data.length - 1; i >= 0; i--) {
- if (checkFnSingle(data[i])) return data[i];
- }
- }
- return inputValue;
- });
-
- //Update viewValue if model change
- scope.$watch('$select.selected', function(newValue) {
- if (ngModel.$viewValue !== newValue) {
- ngModel.$setViewValue(newValue);
- }
- });
-
- ngModel.$render = function() {
- $select.selected = ngModel.$viewValue;
- };
-
- scope.$on('uis:select', function (event, item) {
- $select.selected = item;
- });
-
- scope.$on('uis:close', function (event, skipFocusser) {
- $timeout(function(){
- $select.focusser.prop('disabled', false);
- if (!skipFocusser) $select.focusser[0].focus();
- },0,false);
- });
-
- scope.$on('uis:activate', function () {
- focusser.prop('disabled', true); //Will reactivate it on .close()
- });
-
- //Idea from: https://github.com/ivaynberg/select2/blob/79b5bf6db918d7560bdd959109b7bcfb47edaf43/select2.js#L1954
- var focusser = angular.element("");
- $compile(focusser)(scope);
- $select.focusser = focusser;
-
- //Input that will handle focus
- $select.focusInput = focusser;
-
- element.parent().append(focusser);
- focusser.bind("focus", function(){
- scope.$evalAsync(function(){
- $select.focus = true;
- });
- });
- focusser.bind("blur", function(){
- scope.$evalAsync(function(){
- $select.focus = false;
- });
- });
- focusser.bind("keydown", function(e){
-
- if (e.which === KEY.BACKSPACE) {
- e.preventDefault();
- e.stopPropagation();
- $select.select(undefined);
- scope.$apply();
- return;
- }
-
- if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
- return;
- }
-
- if (e.which == KEY.DOWN || e.which == KEY.UP || e.which == KEY.ENTER || e.which == KEY.SPACE){
- e.preventDefault();
- e.stopPropagation();
- $select.activate();
- }
-
- scope.$digest();
- });
-
- focusser.bind("keyup input", function(e){
-
- if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC || e.which == KEY.ENTER || e.which === KEY.BACKSPACE) {
- return;
- }
-
- $select.activate(focusser.val()); //User pressed some regular key, so we pass it to the search input
- focusser.val('');
- scope.$digest();
-
- });
-
-
- }
- };
-}]);
-
-// Make multiple matches sortable
-uis.directive('uiSelectSort', ['$timeout', 'uiSelectConfig', 'uiSelectMinErr', function($timeout, uiSelectConfig, uiSelectMinErr) {
- return {
- require: ['^^uiSelect', '^ngModel'],
- link: function(scope, element, attrs, ctrls) {
- if (scope[attrs.uiSelectSort] === null) {
- throw uiSelectMinErr('sort', 'Expected a list to sort');
- }
-
- var $select = ctrls[0];
- var $ngModel = ctrls[1];
-
- var options = angular.extend({
- axis: 'horizontal'
- },
- scope.$eval(attrs.uiSelectSortOptions));
-
- var axis = options.axis;
- var draggingClassName = 'dragging';
- var droppingClassName = 'dropping';
- var droppingBeforeClassName = 'dropping-before';
- var droppingAfterClassName = 'dropping-after';
-
- scope.$watch(function(){
- return $select.sortable;
- }, function(newValue){
- if (newValue) {
- element.attr('draggable', true);
- } else {
- element.removeAttr('draggable');
- }
- });
-
- element.on('dragstart', function(event) {
- element.addClass(draggingClassName);
-
- (event.dataTransfer || event.originalEvent.dataTransfer).setData('text', scope.$index.toString());
- });
-
- element.on('dragend', function() {
- removeClass(draggingClassName);
- });
-
- var move = function(from, to) {
- /*jshint validthis: true */
- this.splice(to, 0, this.splice(from, 1)[0]);
- };
-
- var removeClass = function(className) {
- angular.forEach($select.$element.querySelectorAll('.' + className), function(el){
- angular.element(el).removeClass(className);
- });
- };
-
- var dragOverHandler = function(event) {
- event.preventDefault();
-
- var offset = axis === 'vertical' ? event.offsetY || event.layerY || (event.originalEvent ? event.originalEvent.offsetY : 0) : event.offsetX || event.layerX || (event.originalEvent ? event.originalEvent.offsetX : 0);
-
- if (offset < (this[axis === 'vertical' ? 'offsetHeight' : 'offsetWidth'] / 2)) {
- removeClass(droppingAfterClassName);
- element.addClass(droppingBeforeClassName);
-
- } else {
- removeClass(droppingBeforeClassName);
- element.addClass(droppingAfterClassName);
- }
- };
-
- var dropTimeout;
-
- var dropHandler = function(event) {
- event.preventDefault();
-
- var droppedItemIndex = parseInt((event.dataTransfer || event.originalEvent.dataTransfer).getData('text'), 10);
-
- // prevent event firing multiple times in firefox
- $timeout.cancel(dropTimeout);
- dropTimeout = $timeout(function() {
- _dropHandler(droppedItemIndex);
- }, 20);
- };
-
- var _dropHandler = function(droppedItemIndex) {
- var theList = scope.$eval(attrs.uiSelectSort);
- var itemToMove = theList[droppedItemIndex];
- var newIndex = null;
-
- if (element.hasClass(droppingBeforeClassName)) {
- if (droppedItemIndex < scope.$index) {
- newIndex = scope.$index - 1;
- } else {
- newIndex = scope.$index;
- }
- } else {
- if (droppedItemIndex < scope.$index) {
- newIndex = scope.$index;
- } else {
- newIndex = scope.$index + 1;
- }
- }
-
- move.apply(theList, [droppedItemIndex, newIndex]);
-
- $ngModel.$setViewValue(Date.now());
-
- scope.$apply(function() {
- scope.$emit('uiSelectSort:change', {
- array: theList,
- item: itemToMove,
- from: droppedItemIndex,
- to: newIndex
- });
- });
-
- removeClass(droppingClassName);
- removeClass(droppingBeforeClassName);
- removeClass(droppingAfterClassName);
-
- element.off('drop', dropHandler);
- };
-
- element.on('dragenter', function() {
- if (element.hasClass(draggingClassName)) {
- return;
- }
-
- element.addClass(droppingClassName);
-
- element.on('dragover', dragOverHandler);
- element.on('drop', dropHandler);
- });
-
- element.on('dragleave', function(event) {
- if (event.target != element) {
- return;
- }
-
- removeClass(droppingClassName);
- removeClass(droppingBeforeClassName);
- removeClass(droppingAfterClassName);
-
- element.off('dragover', dragOverHandler);
- element.off('drop', dropHandler);
- });
- }
- };
-}]);
-
-/**
- * Debounces functions
- *
- * Taken from UI Bootstrap $$debounce source code
- * See https://github.com/angular-ui/bootstrap/blob/master/src/debounce/debounce.js
- *
- */
-uis.factory('$$uisDebounce', ['$timeout', function($timeout) {
- return function(callback, debounceTime) {
- var timeoutPromise;
-
- return function() {
- var self = this;
- var args = Array.prototype.slice.call(arguments);
- if (timeoutPromise) {
- $timeout.cancel(timeoutPromise);
- }
-
- timeoutPromise = $timeout(function() {
- callback.apply(self, args);
- }, debounceTime);
- };
- };
-}]);
-
-uis.directive('uisOpenClose', ['$parse', '$timeout', function ($parse, $timeout) {
- return {
- restrict: 'A',
- require: 'uiSelect',
- link: function (scope, element, attrs, $select) {
- $select.onOpenCloseCallback = $parse(attrs.uisOpenClose);
-
- scope.$watch('$select.open', function (isOpen, previousState) {
- if (isOpen !== previousState) {
- $timeout(function () {
- $select.onOpenCloseCallback(scope, {
- isOpen: isOpen
- });
- });
- }
- });
- }
- };
-}]);
-
-/**
- * Parses "repeat" attribute.
- *
- * Taken from AngularJS ngRepeat source code
- * See https://github.com/angular/angular.js/blob/v1.2.15/src/ng/directive/ngRepeat.js#L211
- *
- * Original discussion about parsing "repeat" attribute instead of fully relying on ng-repeat:
- * https://github.com/angular-ui/ui-select/commit/5dd63ad#commitcomment-5504697
- */
-
-uis.service('uisRepeatParser', ['uiSelectMinErr','$parse', function(uiSelectMinErr, $parse) {
- var self = this;
-
- /**
- * Example:
- * expression = "address in addresses | filter: {street: $select.search} track by $index"
- * itemName = "address",
- * source = "addresses | filter: {street: $select.search}",
- * trackByExp = "$index",
- */
- self.parse = function(expression) {
-
-
- var match;
- //var isObjectCollection = /\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)/.test(expression);
- // If an array is used as collection
-
- // if (isObjectCollection){
- // 000000000000000000000000000000111111111000000000000000222222222222220033333333333333333333330000444444444444444444000000000000000055555555555000000000000000000000066666666600000000
- match = expression.match(/^\s*(?:([\s\S]+?)\s+as\s+)?(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(\s*[\s\S]+?)?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
-
- // 1 Alias
- // 2 Item
- // 3 Key on (key,value)
- // 4 Value on (key,value)
- // 5 Source expression (including filters)
- // 6 Track by
-
- if (!match) {
- throw uiSelectMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
- expression);
- }
-
- var source = match[5],
- filters = '';
-
- // When using (key,value) ui-select requires filters to be extracted, since the object
- // is converted to an array for $select.items
- // (in which case the filters need to be reapplied)
- if (match[3]) {
- // Remove any enclosing parenthesis
- source = match[5].replace(/(^\()|(\)$)/g, '');
- // match all after | but not after ||
- var filterMatch = match[5].match(/^\s*(?:[\s\S]+?)(?:[^\|]|\|\|)+([\s\S]*)\s*$/);
- if(filterMatch && filterMatch[1].trim()) {
- filters = filterMatch[1];
- source = source.replace(filters, '');
- }
- }
-
- return {
- itemName: match[4] || match[2], // (lhs) Left-hand side,
- keyName: match[3], //for (key, value) syntax
- source: $parse(source),
- filters: filters,
- trackByExp: match[6],
- modelMapper: $parse(match[1] || match[4] || match[2]),
- repeatExpression: function (grouped) {
- var expression = this.itemName + ' in ' + (grouped ? '$group.items' : '$select.items');
- if (this.trackByExp) {
- expression += ' track by ' + this.trackByExp;
- }
- return expression;
- }
- };
-
- };
-
- self.getGroupNgRepeatExpression = function() {
- return '$group in $select.groups track by $group.name';
- };
-
-}]);
-
-}());
-angular.module("ui.select").run(["$templateCache", function($templateCache) {$templateCache.put("bootstrap/choices.tpl.html","");
-$templateCache.put("bootstrap/match-multiple.tpl.html"," × ");
-$templateCache.put("bootstrap/match.tpl.html","");
-$templateCache.put("bootstrap/no-choice.tpl.html","");
-$templateCache.put("bootstrap/select-multiple.tpl.html","");
-$templateCache.put("bootstrap/select.tpl.html","");
-$templateCache.put("select2/choices.tpl.html","");
-$templateCache.put("select2/match-multiple.tpl.html"," ");
-$templateCache.put("select2/match.tpl.html","{{$select.placeholder}} ");
-$templateCache.put("select2/no-choice.tpl.html","");
-$templateCache.put("select2/select-multiple.tpl.html","");
-$templateCache.put("select2/select.tpl.html","");
-$templateCache.put("selectize/choices.tpl.html","");
-$templateCache.put("selectize/match-multiple.tpl.html"," ×
");
-$templateCache.put("selectize/match.tpl.html","{{$select.placeholder}}
");
-$templateCache.put("selectize/no-choice.tpl.html","");
-$templateCache.put("selectize/select-multiple.tpl.html","");
-$templateCache.put("selectize/select.tpl.html","");}]);
\ No newline at end of file